Use RV config string rather than FDT
authorAndrew Waterman <waterman@cs.berkeley.edu>
Tue, 1 Mar 2016 23:01:29 +0000 (15:01 -0800)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Wed, 2 Mar 2016 20:15:25 +0000 (12:15 -0800)
riscv/devicetree.h [deleted file]
riscv/sim.cc
riscv/sim.h

diff --git a/riscv/devicetree.h b/riscv/devicetree.h
deleted file mode 100644 (file)
index 5d4a871..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-// See LICENSE for license details.
-
-#ifndef _RISCV_DEVICETREE_H
-#define _RISCV_DEVICETREE_H
-
-#include <stdint.h>
-#include <string.h>
-#include <string>
-#include <map>
-#include <vector>
-#include <arpa/inet.h>
-
-#define FDT_MAGIC 0xd00dfeedU
-#define FDT_VERSION 17
-#define FDT_COMP_VERSION 16
-#define FDT_BEGIN_NODE 1
-#define FDT_END_NODE 2
-#define FDT_PROP 3
-#define FDT_END 9
-
-struct fdt_header {
-  uint32_t magic;
-  uint32_t totalsize;
-  uint32_t off_dt_struct;
-  uint32_t off_dt_strings;
-  uint32_t off_rsvmap;
-  uint32_t version;
-  uint32_t last_comp_version;
-  uint32_t boot_cpuid_phys;
-  uint32_t size_dt_strings;
-  uint32_t size_dt_struct;
-};
-
-struct fdt_reserve_entry {
-  uint64_t address;
-  uint64_t size;
-};
-
-struct string_table {
-  std::map<std::string, size_t> strings;
-  std::vector<char> data;
-
-  size_t add(std::string s) {
-    if (!strings.count(s)) {
-      strings[s] = data.size();
-      data.insert(data.end(), s.begin(), s.end());
-      data.push_back(0);
-    }
-    return strings[s];
-  }
-};
-
-struct device_tree {
-  device_tree() {
-    memset(rsvmap, 0, sizeof(rsvmap));
-  }
-
-  void begin_node(std::string s) {
-    std::vector<uint32_t> name = s2v(s);
-    sblock.push_back(FDT_BEGIN_NODE);
-    sblock.insert(sblock.end(), name.begin(), name.end());
-  }
-
-  void end_node() {
-    sblock.push_back(FDT_END_NODE);
-  }
-
-  std::vector<char> finalize() {
-    sblock.push_back(FDT_END);
-
-    struct fdt_header h;
-    h.size_dt_struct = sblock.size() * sizeof(sblock[0]);
-    h.size_dt_strings = strings.data.size();
-    h.magic = FDT_MAGIC;
-    h.off_rsvmap = sizeof(h);
-    h.off_dt_struct = h.off_rsvmap + sizeof(rsvmap);
-    h.off_dt_strings = h.off_dt_struct + h.size_dt_struct;
-    h.totalsize = h.off_dt_strings + h.size_dt_strings;
-    h.version = FDT_VERSION;
-    h.last_comp_version = FDT_COMP_VERSION;
-    h.boot_cpuid_phys = 0;
-
-    for (uint32_t* p = &h.magic; p < &h.magic + sizeof(h)/sizeof(uint32_t); p++)
-      *p = htonl(*p);
-    for (uint32_t& p : sblock)
-      p = htonl(p);
-
-    std::vector<char> res;
-    res.insert(res.end(), (char*)&h, (char*)&h + sizeof(h));
-    res.insert(res.end(), (char*)&rsvmap, (char*)&rsvmap + sizeof(rsvmap));
-    res.insert(res.end(), (char*)&sblock[0],
-               (char*)&sblock[0] + sblock.size() * sizeof(sblock[0]));
-    res.insert(res.end(), strings.data.begin(), strings.data.end());
-    return res;
-  }
-  
-  void add_prop(std::string name, uint32_t data)
-  {
-    add_prop(name, std::vector<uint32_t>(1, data), sizeof(data));
-  }
-  
-  void add_reg(std::vector<uint64_t> values)
-  {
-    std::vector<uint32_t> v;
-    for (auto x : values) {
-      v.push_back(x >> 32);
-      v.push_back(x);
-    }
-    add_prop("reg", v, v.size() * sizeof(v[0]));
-  }
-  
-  void add_prop(std::string name, std::string data)
-  {
-    add_prop(name, s2v(data), data.size()+1);
-  }
-
- private:
-  struct string_table strings;
-  std::vector<uint32_t> sblock;
-  struct fdt_reserve_entry rsvmap[1];
-
-  std::vector<uint32_t> s2v(std::string data) {
-    std::vector<char> v(data.begin(), data.end());
-    do {
-      v.push_back(0);
-    } while (v.size() % 4);
-  
-    std::vector<uint32_t> words;
-    for (size_t i = 0; i < v.size(); i += 4)
-      words.push_back((v[i] << 24) | (v[i+1] << 16) | (v[i+2] << 8) | v[i+3]);
-    return words;
-  }
-  
-  void add_prop(std::string name, std::vector<uint32_t> data, size_t len) {
-    sblock.push_back(FDT_PROP);
-    sblock.push_back(len);
-    sblock.push_back(strings.add(name));
-    sblock.insert(sblock.end(), data.begin(), data.end());
-  }
-};
-
-#endif
index 5de93f294c287b1d7fb040cd259f36a348ea604c..f32de2bcc870acdbf19b75419dd664a41df47c8d 100644 (file)
@@ -2,9 +2,9 @@
 
 #include "sim.h"
 #include "htif.h"
-#include "devicetree.h"
 #include <map>
 #include <iostream>
+#include <sstream>
 #include <climits>
 #include <cstdlib>
 #include <cassert>
@@ -45,7 +45,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb,
   for (size_t i = 0; i < procs.size(); i++)
     procs[i] = new processor_t(isa, this, i);
 
-  make_device_tree();
+  make_config_string();
 }
 
 sim_t::~sim_t()
@@ -155,40 +155,42 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
   return bus.store(addr, len, bytes);
 }
 
-void sim_t::make_device_tree()
+void sim_t::make_config_string()
 {
-  char buf[32];
-  size_t max_devtree_size = procs.size() * 4096; // sloppy upper bound
-  size_t cpu_size = NCSR * procs[0]->max_xlen / 8;
-  reg_t cpu_addr = memsz + max_devtree_size;
-
-  device_tree dt;
-  dt.begin_node("");
-  dt.add_prop("#address-cells", 2);
-  dt.add_prop("#size-cells", 2);
-  dt.add_prop("model", "Spike");
-    dt.begin_node("memory@0");
-      dt.add_prop("device_type", "memory");
-      dt.add_reg({0, memsz});
-    dt.end_node();
-    dt.begin_node("cpus");
-      dt.add_prop("#address-cells", 2);
-      dt.add_prop("#size-cells", 2);
-      for (size_t i = 0; i < procs.size(); i++) {
-        sprintf(buf, "cpu@%" PRIx64, cpu_addr);
-        dt.begin_node(buf);
-          dt.add_prop("device_type", "cpu");
-          dt.add_prop("compatible", "riscv");
-          dt.add_prop("isa", procs[i]->isa_string);
-          dt.add_reg({cpu_addr});
-        dt.end_node();
-
-        bus.add_device(cpu_addr, procs[i]);
-        cpu_addr += cpu_size;
-      }
-    dt.end_node();
-  dt.end_node();
-
-  devicetree.reset(new rom_device_t(dt.finalize()));
-  bus.add_device(memsz, devicetree.get());
+  size_t csr_size = NCSR * 16 /* RV128 */;
+  size_t device_tree_addr = memsz;
+  size_t cpu_addr = memsz + csr_size;
+
+  std::stringstream s;
+  s << std::hex <<
+        "platform {\n"
+        "  vendor ucb;\n"
+        "  arch spike;\n"
+        "};\n"
+        "ram {\n"
+        "  0 {\n"
+        "    addr 0;\n"
+        "    size 0x" << memsz << ";\n"
+        "  };\n"
+        "};\n"
+        "core {\n";
+  for (size_t i = 0; i < procs.size(); i++) {
+    s <<
+        "  " << i << " {\n"
+        "    " << "0 {\n" << // hart 0 on core i
+        "      isa " << procs[i]->isa_string << ";\n"
+        "      addr 0x" << cpu_addr << ";\n"
+        "    };\n"
+        "  };\n";
+    bus.add_device(cpu_addr, procs[i]);
+    cpu_addr += csr_size;
+  }
+  s <<  "};\n";
+
+  std::string str = s.str();
+  std::vector<char> vec(str.begin(), str.end());
+  vec.push_back(0);
+  assert(vec.size() <= csr_size);
+  config_string.reset(new rom_device_t(vec));
+  bus.add_device(memsz, config_string.get());
 }
index 6ef2c824c5f9d171dc1241e55a80ff1a0a8368a0..6745e75f8e9694db330a990d032ca4ff9151e7b9 100644 (file)
@@ -43,7 +43,7 @@ private:
   size_t memsz; // memory size in bytes
   mmu_t* debug_mmu;  // debug port into main memory
   std::vector<processor_t*> procs;
-  std::unique_ptr<rom_device_t> devicetree;
+  std::unique_ptr<rom_device_t> config_string;
   bus_t bus;
 
   processor_t* get_core(const std::string& i);
@@ -60,7 +60,7 @@ private:
   // memory-mapped I/O routines
   bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
   bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
-  void make_device_tree();
+  void make_config_string();
 
   // presents a prompt for introspection into the simulation
   void interactive();