--- Log opened Mon Nov 07 00:00:31 2016 | ||
shorne_ | oh man, after a long time of debugging strace works, I saw missing linux patch a966c95 openrisc: include l.swa in check for write data pagefault | 10:15 |
---|---|---|
shorne_ | thats why the l.lwa/l.swa was going crazy | 10:17 |
-!- rhythmx_ is now known as rhythmx | 10:29 | |
-!- Marcus is now known as Guest74999 | 11:24 | |
kc5tja | ZipCPU: Since we keep missing each other, I'll just say what I wanted to chat interactively about. | 11:37 |
ZipCPU | Go ahead, I'm here now. | 11:37 |
kc5tja | ZipCPU: I wanted to chat w/ you on the use of Verilator to run my example design (that iverilog has so much problems with), eventually in a CI/CD environment. | 11:38 |
kc5tja | ZipCPU: You'd mentioned that you had experience in this area, and I think I could use some guidance. Where would I begin the migration from iverilog to Verilator? | 11:38 |
ZipCPU | First step, let's figure out how to run verilator. Are all your files in the same directory? | 11:39 |
ZipCPU | I tend to use: verilator -y dir1 -y dir2 -cc toplevel.v, where dir1 and dir2 contain Verilog sources in addition to the current directory containing toplevel.v | 11:40 |
kc5tja | No; all CPU-implementation files are in rtl/verilog, while the example modules are located in docs/example | 11:46 |
kc5tja | That's easy enough so far. | 11:47 |
SMDwrk | ZipCPU Should I implement any wrap over toplvl.v? | 11:47 |
ZipCPU | With that line, verilator makes a set of C++ source files, placed into a new subdirectory obj_dir. | 11:48 |
ZipCPU | SMDwrk, Actually, I go the other way. | 11:48 |
ZipCPU | I usually separate everything Xilinx independent into a file I call busmaster.v, leaving toplevel.v with the Xilinx parts and pieces that Verilator could never support. | 11:48 |
ZipCPU | So, in my case, I would do "verilator -cc busmaster.v" (busmaster.v is the name of my hand-built WB interconnect, but it also contains just about every thing else as a sub-module.) | 11:49 |
ZipCPU | If you'd like, you can take a look at the Makefile in https://github.com/ZipCPU/openarty, within the rtl/ subdirectory. | 11:50 |
ZipCPU | kc5tja: The next step is to build the Verilator library. To do that, go into obj_dir and run "make -f Vtoplevel.mk". | 11:50 |
Finde | how much VPI stuff does verilator support? | 11:51 |
ZipCPU | At that point, you'll have a Vtoplevel__ALL.a. | 11:52 |
ZipCPU | Finde: I'm not familiar with VPI, so ... I guess I don't know. | 11:52 |
ZipCPU | I have never invoked C/C++ from Verilog. I've only invoked Verilog (via verilator) using C/C++. | 11:52 |
kc5tja | OK, so far Verilator is serving as a means of compiling Verilog directly into C/C++ code, which is then linked into a static library. | 11:53 |
Finde | mm ok | 11:53 |
ZipCPU | Yup! | 11:53 |
Finde | looking into adding verilator support in openpiton | 11:53 |
Finde | got somewhere with icarus but it ended up getting frozen at some point | 11:53 |
kc5tja | Finde: OMG, that is *exactly* what happened to me. | 11:53 |
kc5tja | My model simulates perfectly in Xilinx ISE, but that's not exactly Travis CI friendly. ;) | 11:54 |
ZipCPU | Next lesson: Take a peek at the "CONNECTING TO C++" section of the Verilator manual, "http://www.veripool.org/projects/verilator/wiki/manual-verilator#CONNECTING-TO-C" | 11:55 |
ZipCPU | Specifically, Verilator gives you the ability to create an object of the type of your top level. Members (i.e. variables) of that object include all of your top level I/O's. | 11:56 |
ZipCPU | Not as well documented is the fact that members also include access to *all* of your internal clocked registers. | 11:56 |
ZipCPU | That's been my saving grace: being able to printf any internal variable at will, and as necessary. | 11:56 |
ZipCPU | Further, when things have gotten *really* messed up, I've been able to look into, examine, and debug the C++ code Verilator generates because, well, I've got it in front of me and I can do with it as I please. | 11:57 |
* kc5tja nods | 11:58 | |
kc5tja | The structure of that main loop reminds me a lot of how I wrote my lib65816 library for 65816 CPU emulation. | 11:58 |
ZipCPU | The big basics of the host C++ main loop is toggle clock, call eval(), toggle clock, call eval(), etc. | 11:58 |
ZipCPU | The next trick, though, comes in ... how do I hook up external peripherals to this simulation? | 11:59 |
kc5tja | So, my top-level in computer.v handles clock toggling. Do I need to manually toggle in C++ code too? That seems redundant. | 11:59 |
ZipCPU | Perhaps you want to run verilator one level below that? | 11:59 |
ZipCPU | I've always controlled all of my clocks from the C++ program controlling the Verilator simulation. | 12:00 |
kc5tja | I'd prefer not to just yet, only because what I have is known-working in Xilinx. I'd prefer to migrate to a better solution only after I get a working example in Verilator first. | 12:00 |
kc5tja | I'll play with it, I guess. It's just a clock. :) | 12:01 |
kc5tja | Anyway, on to emulating peripherals. This is the meaty part. | 12:01 |
ZipCPU | Ok, I have emulations for such things as: DDR3 memories, flash memory, SD cards (SPI port), an MII connected ethernet port, UART, even an OLED display. | 12:03 |
ZipCPU | Further, since I control my CPU via a UART port, I have a Verilator module that will connect the control port to a TCP/IP stream, so that as long as my control programs use TCP/IP, they will never know whether they are talking to the real device or the simulation. | 12:04 |
ZipCPU | Almost forgot ... I do have a (unreleased) VGA controller for Verilator as well. (Both this and the OLED simulation, use the gtkmm and cairomm libraries--although they tend to run *very* slowly) | 12:05 |
ZipCPU | Finde: from the manual, "Verilator supports a very limited subset of the VPI." | 12:06 |
ZipCPU | You can find all of those peripheral emulators copied into the OpenArty project, so you should be able to find them within: https://github.com/ZipCPU/openarty/bench/cpp. | 12:07 |
kc5tja | I'm still not sure how your emulated peripherals are actually called, or how Verilator knows to call them. | 12:26 |
kc5tja | Am I missing something obvious? | 12:26 |
ZipCPU | Ah, okay, yes ... | 12:27 |
ZipCPU | Inside my master C++ file, I call the emulated peripheral. | 12:27 |
kc5tja | Oh, in your main() function then. | 12:27 |
ZipCPU | Yes. | 12:27 |
ZipCPU | Well ... not quite. | 12:27 |
ZipCPU | I usually wrap the object in a class. | 12:27 |
ZipCPU | Within that class, I create a "tick" function. | 12:27 |
kc5tja | Right; you have a tick() method on each. | 12:28 |
ZipCPU | My main function while loop then looks like "while(1) tick();" | 12:28 |
ZipCPU | The tick function does: | 12:28 |
ZipCPU | 1. Update any peripheral outputs, given the inputs to the peripheral. | 12:28 |
ZipCPU | 2. Call the eval() with clock = 0 | 12:28 |
ZipCPU | 3. Call eval() with clock = 1 | 12:28 |
ZipCPU | 4. Call eval() with clock = 0. | 12:28 |
ZipCPU | And returns. | 12:29 |
kc5tja | Oh, why the two calls to eval() with clock=0? | 12:29 |
ZipCPU | The extra clock at zero is to try to compensate from the fact that the peripherals don't really get to use the posedge of the clock. | 12:29 |
kc5tja | Ahh. | 12:29 |
ZipCPU | It evaluates non-clocked logic that depends upon the response of the peripherals. | 12:29 |
ZipCPU | So, for example, the UART peripheral call looks like: | 12:30 |
ZipCPU | m_core->i_uart = uartsim(o_uart); | 12:30 |
kc5tja | But it's conceivable I could write code that: 1. call eval() w/ clock=0. Call tick(). 2. Call eval() w/ clock=1. Call tick(). Yes? | 12:30 |
ZipCPU | Careful ... "tick()" is my construction and it modifies the clock. | 12:30 |
kc5tja | Supposing tick() does not modify the clock. | 12:30 |
ZipCPU | Then just call eval(); | 12:31 |
ZipCPU | The purpose of my tick() function is to advance everything by one clock tick. | 12:31 |
kc5tja | So, your tick() funcs in uartsim do not advance the simulator's concept of time that I can see. | 12:34 |
kc5tja | They update their own local counters, but that's it. | 12:34 |
ZipCPU | Yes. My uartsim assumes that it is called once per clock "tick", but not what constitutes a clock tick. | 12:34 |
kc5tja | Right. | 12:35 |
kc5tja | So this doesn't change what I was thinking. | 12:35 |
kc5tja | OK, split tick() into a tick0() and tick1() method if it helps you conceive what I was talking about. | 12:35 |
kc5tja | Where is your main function located? | 12:38 |
ZipCPU | In the openarty distribution, its in a file called fastmaster_tb.cpp | 12:39 |
ZipCPU | Sorry, that's in the bench/cpp subdirectory. | 12:40 |
kc5tja | Ahh. | 12:40 |
ZipCPU | Somewhere around line 775, you'll find: while(1) tb->tick(); | 12:40 |
kc5tja | Very cool. I will need to play with this when I have more time. Stupid office work is calling. >:( | 12:44 |
ZipCPU | Glad I could help. Let me know if you have more questions. | 12:52 |
ZipCPU | Finde: You too! ;) | 12:52 |
Finde | interesting | 17:16 |
Finde | thanks ZipCPU | 17:16 |
--- Log closed Tue Nov 08 00:00:33 2016 |
Generated by irclog2html.py 2.15.2 by Marius Gedminas - find it at mg.pov.lt!