1 // See LICENSE for license details.
2 
3 #ifndef __HTIF_H
4 #define __HTIF_H
5 
6 #include "memif.h"
7 #include "syscall.h"
8 #include "device.h"
9 #include "byteorder.h"
10 #include <string.h>
11 #include <map>
12 #include <vector>
13 #include <assert.h>
14 
15 class htif_t : public chunked_memif_t
16 {
17  public:
18   htif_t();
19   htif_t(int argc, char** argv);
20   htif_t(const std::vector<std::string>& args);
21   virtual ~htif_t();
22 
23   virtual void start();
24   virtual void stop();
25 
26   int run();
27   bool done();
28   int exit_code();
29 
memif()30   virtual memif_t& memif() { return mem; }
31 
from_target(target_endian<T> n)32   template<typename T> inline T from_target(target_endian<T> n) const
33   {
34 #ifdef RISCV_ENABLE_DUAL_ENDIAN
35     memif_endianness_t endianness = get_target_endianness();
36     assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
37 
38     return endianness == memif_endianness_big? n.from_be() : n.from_le();
39 #else
40     return n.from_le();
41 #endif
42   }
43 
to_target(T n)44   template<typename T> inline target_endian<T> to_target(T n) const
45   {
46 #ifdef RISCV_ENABLE_DUAL_ENDIAN
47     memif_endianness_t endianness = get_target_endianness();
48     assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
49 
50     return endianness == memif_endianness_big? target_endian<T>::to_be(n) : target_endian<T>::to_le(n);
51 #else
52     return target_endian<T>::to_le(n);
53 #endif
54   }
55 
56  protected:
57   virtual void reset() = 0;
58 
59   virtual void read_chunk(addr_t taddr, size_t len, void* dst) = 0;
60   virtual void write_chunk(addr_t taddr, size_t len, const void* src) = 0;
61   virtual void clear_chunk(addr_t taddr, size_t len);
62 
63   virtual size_t chunk_align() = 0;
64   virtual size_t chunk_max_size() = 0;
65 
66   virtual std::map<std::string, uint64_t> load_payload(const std::string& payload, reg_t* entry);
67   virtual void load_program();
idle()68   virtual void idle() {}
69 
host_args()70   const std::vector<std::string>& host_args() { return hargs; }
71 
get_entry_point()72   reg_t get_entry_point() { return entry; }
73 
74   // indicates that the initial program load can skip writing this address
75   // range to memory, because it has already been loaded through a sideband
is_address_preloaded(addr_t taddr,size_t len)76   virtual bool is_address_preloaded(addr_t taddr, size_t len) { return false; }
77 
78   // Given an address, return symbol from addr2symbol map
79   const char* get_symbol(uint64_t addr);
80 
81  private:
82   void parse_arguments(int argc, char ** argv);
83   void register_devices();
84   void usage(const char * program_name);
85 
86   memif_t mem;
87   reg_t entry;
88   bool writezeros;
89   std::vector<std::string> hargs;
90   std::vector<std::string> targs;
91   std::string sig_file;
92   unsigned int line_size;
93   addr_t sig_addr; // torture
94   addr_t sig_len; // torture
95   addr_t tohost_addr;
96   addr_t fromhost_addr;
97   int exitcode;
98   bool stopped;
99 
100   device_list_t device_list;
101   syscall_t syscall_proxy;
102   bcd_t bcd;
103   std::vector<device_t*> dynamic_devices;
104   std::vector<std::string> payloads;
105 
target_args()106   const std::vector<std::string>& target_args() { return targs; }
107 
108   std::map<uint64_t, std::string> addr2symbol;
109 
110   friend class memif_t;
111   friend class syscall_t;
112 };
113 
114 /* Alignment guide for emulator.cc options:
115   -x, --long-option        Description with max 80 characters --------------->\n\
116        +plus-arg-equivalent\n\
117  */
118 #define HTIF_USAGE_OPTIONS \
119 "HOST OPTIONS\n\
120   -h, --help               Display this help and exit\n\
121   +h,  +help\n\
122        +permissive         The host will ignore any unparsed options up until\n\
123                              +permissive-off (Only needed for VCS)\n\
124        +permissive-off     Stop ignoring options. This is mandatory if using\n\
125                              +permissive (Only needed for VCS)\n\
126       --rfb=DISPLAY        Add new remote frame buffer on display DISPLAY\n\
127        +rfb=DISPLAY          to be accessible on 5900 + DISPLAY (default = 0)\n\
128       --signature=FILE     Write torture test signature to FILE\n\
129        +signature=FILE\n\
130       --signature-granularity=VAL           Size of each line in signature.\n\
131        +signature-granularity=VAL\n\
132       --chroot=PATH        Use PATH as location of syscall-servicing binaries\n\
133        +chroot=PATH\n\
134       --payload=PATH       Load PATH memory as an additional ELF payload\n\
135        +payload=PATH\n\
136 \n\
137 HOST OPTIONS (currently unsupported)\n\
138       --disk=DISK          Add DISK device. Use a ramdisk since this isn't\n\
139        +disk=DISK            supported\n\
140 \n\
141 TARGET (RISC-V BINARY) OPTIONS\n\
142   These are the options passed to the program executing on the emulated RISC-V\n\
143   microprocessor.\n"
144 
145 #define HTIF_LONG_OPTIONS_OPTIND 1024
146 #define HTIF_LONG_OPTIONS                                               \
147 {"help",      no_argument,       0, 'h'                          },     \
148 {"rfb",       optional_argument, 0, HTIF_LONG_OPTIONS_OPTIND     },     \
149 {"disk",      required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 1 },     \
150 {"signature", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 2 },     \
151 {"chroot",    required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 3 },     \
152 {"payload",   required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 4 },     \
153 {"signature-granularity",    optional_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 5 },     \
154 {0, 0, 0, 0}
155 
156 #endif // __HTIF_H
157