' + 106 | '' + 107 | _("Hide Search Matches") + 108 | "
" 109 | ) 110 | ); 111 | }, 112 | 113 | /** 114 | * helper function to hide the search marks again 115 | */ 116 | hideSearchWords: () => { 117 | document 118 | .querySelectorAll("#searchbox .highlight-link") 119 | .forEach((el) => el.remove()); 120 | document 121 | .querySelectorAll("span.highlighted") 122 | .forEach((el) => el.classList.remove("highlighted")); 123 | localStorage.removeItem("sphinx_highlight_terms") 124 | }, 125 | 126 | initEscapeListener: () => { 127 | // only install a listener if it is really needed 128 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; 129 | 130 | document.addEventListener("keydown", (event) => { 131 | // bail for input elements 132 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 133 | // bail with special keys 134 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; 135 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { 136 | SphinxHighlight.hideSearchWords(); 137 | event.preventDefault(); 138 | } 139 | }); 140 | }, 141 | }; 142 | 143 | _ready(SphinxHighlight.highlightSearchWords); 144 | _ready(SphinxHighlight.initEscapeListener); 145 | -------------------------------------------------------------------------------- /documents/PyHGL/1-basic/start.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | `python -m pip install pyhgl` 4 | 5 | 6 | ## Syntax 7 | 8 | 9 | PyHGL adds some syntactic sugar to Python and uses a parser generated by [Pegen](https://github.com/we-like-parsers/pegen). PyHGL source files (with `.pyh` suffix) should be imported by a normal python file that has imported `pyhgl`. 10 | 11 | ```py 12 | # in Adder.pyh 13 | from pyhgl.logic import * 14 | ... 15 | # in main.py 16 | import pyhgl 17 | import Adder 18 | ``` 19 | 20 | new operators and statements are listed below. 21 | 22 | ### Operator 23 | 24 | 25 | | Operator | Description | 26 | | -------------- | --------------------- | 27 | | `!x` | LogicNot | 28 | | `x && y` | LogicAnd | 29 | | `x \|\| y` | LogicOr | 30 | | `x \|-> y` | Imply(Assertion) | 31 | | `x >>> y` | Sequential(Assertion) | 32 | | `x <== y` | Assignment | 33 | | `x[idx] <== y` | Partial Assignment | 34 | | `x <=> y` | Connect | 35 | 36 | 37 | ### One-line Decorator 38 | 39 | ```py 40 | # pyhgl 41 | @decorator NAME: 42 | ... 43 | # python 44 | @decorator 45 | def NAME(): 46 | ... 47 | return locals() 48 | ``` 49 | 50 | ### When Statement 51 | 52 | ```py 53 | when signal: 54 | ... 55 | elsewhen signal: 56 | ... 57 | otherwise: 58 | ... 59 | ``` 60 | 61 | ### Switch Statement 62 | 63 | ```py 64 | switch signal: 65 | once a, b: 66 | ... 67 | once c: 68 | ... 69 | once ...: 70 | ... 71 | ``` 72 | 73 | 74 | ## Example 75 | 76 | a Game of Life example comes from [Chisel Tutorials](https://github.com/ucb-bar/chisel-tutorial). 77 | 78 | in `life.pyh` 79 | 80 | ```py 81 | from pyhgl.logic import * 82 | 83 | @module Life(rows, cols): # declares a module `Life` 84 | cells = Reg(Array.zeros(rows, cols)) @ Output # a rows*cols array of 1-bit regs 85 | running = UInt(0) @ Input # control signal. if 1, run; if 0, write data 86 | wdata = UInt(0) @ Input # data to write 87 | waddr_row = UInt(rows) @ Input # write address 88 | waddr_col = UInt(cols) @ Input # write address 89 | 90 | def make_cell(row, col): # row and col are indexes 91 | neighbors = cells[[row-1,row,(row+1)%rows], # select a 3*3 range circularly 92 | [col-1,col,(col+1)%cols]] 93 | cell = neighbors[1,1] # select current cell 94 | neighbors[1,1] = UInt('3:b0') # 3 bits to count 8 neighbors 95 | count_neighbors = Add(neighbors, axis=(0,1)) # sum up the 3*3 array, return a 3-bit uint 96 | when !running: # write data 97 | when waddr_row == row && waddr_col == col: 98 | cell <== wdata 99 | otherwise: # next state 100 | when count_neighbors == 3: # n=3, becomes a live cell 101 | cell <== 1 102 | elsewhen count_neighbors != 2: # n!=3 and n!=2, dies 103 | cell <== 0 104 | # otherwise keep the state 105 | for i in range(rows): 106 | for j in range(cols): 107 | make_cell(i,j) # map rules on each cell 108 | 109 | 110 | @task test_life(self, dut): # coroutine-based simulation tasks 111 | # dut is a `Life` module instance 112 | @task set_mode(self, run: bool): # declares a task 113 | setv(dut.running, run) # `setv` set value to signal/signals 114 | yield self.clock_n() # wait until next negedge of default clock 115 | @task write(self, row, col): # write `1` to a specific cell 116 | setv(dut.wdata, 1) 117 | setv(dut.waddr_row, row) 118 | setv(dut.waddr_col, col) 119 | yield self.clock_n() 120 | @task init_glider(self): 121 | # wait and execute these tasks sequentially 122 | yield write(3,3), write(3,5), write(4,4), write(4,5), write(5,4) 123 | @task show(self): 124 | cells_str = Map(lambda v: '*' if v==1 else ' ', getv(dut.cells)) 125 | for row in cells_str: 126 | print(' '.join(row)) 127 | yield self.clock_n() 128 | 129 | yield set_mode(0), init_glider(), set_mode(1) 130 | for _ in range(20): 131 | yield show() 132 | 133 | 134 | with Session() as sess: # enter a `Session` before initialization 135 | life = Life(10,10) # a 10*10 game of life 136 | sess.track(life) # track all singals in the module 137 | sess.join(test_life(life)) # wait until the task finishes 138 | sess.dumpVCD('life.vcd') # generate waveform to ./build/life.vcd 139 | sess.dumpVerilog('life.sv') # generate RTL to ./build/life.sv 140 | print(sess) # a summary 141 | ``` 142 | 143 | in `main.py` 144 | 145 | ```py 146 | import pyhgl 147 | import life 148 | ``` 149 | 150 | run: `python main.py` -------------------------------------------------------------------------------- /docs/_sources/PyHGL/1-basic/start.md.txt: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | `python -m pip install pyhgl` 4 | 5 | 6 | ## Syntax 7 | 8 | 9 | PyHGL adds some syntactic sugar to Python and uses a parser generated by [Pegen](https://github.com/we-like-parsers/pegen). PyHGL source files (with `.pyh` suffix) should be imported by a normal python file that has imported `pyhgl`. 10 | 11 | ```py 12 | # in Adder.pyh 13 | from pyhgl.logic import * 14 | ... 15 | # in main.py 16 | import pyhgl 17 | import Adder 18 | ``` 19 | 20 | new operators and statements are listed below. 21 | 22 | ### Operator 23 | 24 | 25 | | Operator | Description | 26 | | -------------- | --------------------- | 27 | | `!x` | LogicNot | 28 | | `x && y` | LogicAnd | 29 | | `x \|\| y` | LogicOr | 30 | | `x \|-> y` | Imply(Assertion) | 31 | | `x >>> y` | Sequential(Assertion) | 32 | | `x <== y` | Assignment | 33 | | `x[idx] <== y` | Partial Assignment | 34 | | `x <=> y` | Connect | 35 | 36 | 37 | ### One-line Decorator 38 | 39 | ```py 40 | # pyhgl 41 | @decorator NAME: 42 | ... 43 | # python 44 | @decorator 45 | def NAME(): 46 | ... 47 | return locals() 48 | ``` 49 | 50 | ### When Statement 51 | 52 | ```py 53 | when signal: 54 | ... 55 | elsewhen signal: 56 | ... 57 | otherwise: 58 | ... 59 | ``` 60 | 61 | ### Switch Statement 62 | 63 | ```py 64 | switch signal: 65 | once a, b: 66 | ... 67 | once c: 68 | ... 69 | once ...: 70 | ... 71 | ``` 72 | 73 | 74 | ## Example 75 | 76 | a Game of Life example comes from [Chisel Tutorials](https://github.com/ucb-bar/chisel-tutorial). 77 | 78 | in `life.pyh` 79 | 80 | ```py 81 | from pyhgl.logic import * 82 | 83 | @module Life(rows, cols): # declares a module `Life` 84 | cells = Reg(Array.zeros(rows, cols)) @ Output # a rows*cols array of 1-bit regs 85 | running = UInt(0) @ Input # control signal. if 1, run; if 0, write data 86 | wdata = UInt(0) @ Input # data to write 87 | waddr_row = UInt(rows) @ Input # write address 88 | waddr_col = UInt(cols) @ Input # write address 89 | 90 | def make_cell(row, col): # row and col are indexes 91 | neighbors = cells[[row-1,row,(row+1)%rows], # select a 3*3 range circularly 92 | [col-1,col,(col+1)%cols]] 93 | cell = neighbors[1,1] # select current cell 94 | neighbors[1,1] = UInt('3:b0') # 3 bits to count 8 neighbors 95 | count_neighbors = Add(neighbors, axis=(0,1)) # sum up the 3*3 array, return a 3-bit uint 96 | when !running: # write data 97 | when waddr_row == row && waddr_col == col: 98 | cell <== wdata 99 | otherwise: # next state 100 | when count_neighbors == 3: # n=3, becomes a live cell 101 | cell <== 1 102 | elsewhen count_neighbors != 2: # n!=3 and n!=2, dies 103 | cell <== 0 104 | # otherwise keep the state 105 | for i in range(rows): 106 | for j in range(cols): 107 | make_cell(i,j) # map rules on each cell 108 | 109 | 110 | @task test_life(self, dut): # coroutine-based simulation tasks 111 | # dut is a `Life` module instance 112 | @task set_mode(self, run: bool): # declares a task 113 | setv(dut.running, run) # `setv` set value to signal/signals 114 | yield self.clock_n() # wait until next negedge of default clock 115 | @task write(self, row, col): # write `1` to a specific cell 116 | setv(dut.wdata, 1) 117 | setv(dut.waddr_row, row) 118 | setv(dut.waddr_col, col) 119 | yield self.clock_n() 120 | @task init_glider(self): 121 | # wait and execute these tasks sequentially 122 | yield write(3,3), write(3,5), write(4,4), write(4,5), write(5,4) 123 | @task show(self): 124 | cells_str = Map(lambda v: '*' if v==1 else ' ', getv(dut.cells)) 125 | for row in cells_str: 126 | print(' '.join(row)) 127 | yield self.clock_n() 128 | 129 | yield set_mode(0), init_glider(), set_mode(1) 130 | for _ in range(20): 131 | yield show() 132 | 133 | 134 | with Session() as sess: # enter a `Session` before initialization 135 | life = Life(10,10) # a 10*10 game of life 136 | sess.track(life) # track all singals in the module 137 | sess.join(test_life(life)) # wait until the task finishes 138 | sess.dumpVCD('life.vcd') # generate waveform to ./build/life.vcd 139 | sess.dumpVerilog('life.sv') # generate RTL to ./build/life.sv 140 | print(sess) # a summary 141 | ``` 142 | 143 | in `main.py` 144 | 145 | ```py 146 | import pyhgl 147 | import life 148 | ``` 149 | 150 | run: `python main.py` -------------------------------------------------------------------------------- /docs/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; 14 | 15 | 16 | /* Non-minified version is copied as a separate JS file, is available */ 17 | 18 | /** 19 | * Porter Stemmer 20 | */ 21 | var Stemmer = function() { 22 | 23 | var step2list = { 24 | ational: 'ate', 25 | tional: 'tion', 26 | enci: 'ence', 27 | anci: 'ance', 28 | izer: 'ize', 29 | bli: 'ble', 30 | alli: 'al', 31 | entli: 'ent', 32 | eli: 'e', 33 | ousli: 'ous', 34 | ization: 'ize', 35 | ation: 'ate', 36 | ator: 'ate', 37 | alism: 'al', 38 | iveness: 'ive', 39 | fulness: 'ful', 40 | ousness: 'ous', 41 | aliti: 'al', 42 | iviti: 'ive', 43 | biliti: 'ble', 44 | logi: 'log' 45 | }; 46 | 47 | var step3list = { 48 | icate: 'ic', 49 | ative: '', 50 | alize: 'al', 51 | iciti: 'ic', 52 | ical: 'ic', 53 | ful: '', 54 | ness: '' 55 | }; 56 | 57 | var c = "[^aeiou]"; // consonant 58 | var v = "[aeiouy]"; // vowel 59 | var C = c + "[^aeiouy]*"; // consonant sequence 60 | var V = v + "[aeiou]*"; // vowel sequence 61 | 62 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 63 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 64 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 65 | var s_v = "^(" + C + ")?" + v; // vowel in stem 66 | 67 | this.stemWord = function (w) { 68 | var stem; 69 | var suffix; 70 | var firstch; 71 | var origword = w; 72 | 73 | if (w.length < 3) 74 | return w; 75 | 76 | var re; 77 | var re2; 78 | var re3; 79 | var re4; 80 | 81 | firstch = w.substr(0,1); 82 | if (firstch == "y") 83 | w = firstch.toUpperCase() + w.substr(1); 84 | 85 | // Step 1a 86 | re = /^(.+?)(ss|i)es$/; 87 | re2 = /^(.+?)([^s])s$/; 88 | 89 | if (re.test(w)) 90 | w = w.replace(re,"$1$2"); 91 | else if (re2.test(w)) 92 | w = w.replace(re2,"$1$2"); 93 | 94 | // Step 1b 95 | re = /^(.+?)eed$/; 96 | re2 = /^(.+?)(ed|ing)$/; 97 | if (re.test(w)) { 98 | var fp = re.exec(w); 99 | re = new RegExp(mgr0); 100 | if (re.test(fp[1])) { 101 | re = /.$/; 102 | w = w.replace(re,""); 103 | } 104 | } 105 | else if (re2.test(w)) { 106 | var fp = re2.exec(w); 107 | stem = fp[1]; 108 | re2 = new RegExp(s_v); 109 | if (re2.test(stem)) { 110 | w = stem; 111 | re2 = /(at|bl|iz)$/; 112 | re3 = new RegExp("([^aeiouylsz])\\1$"); 113 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 114 | if (re2.test(w)) 115 | w = w + "e"; 116 | else if (re3.test(w)) { 117 | re = /.$/; 118 | w = w.replace(re,""); 119 | } 120 | else if (re4.test(w)) 121 | w = w + "e"; 122 | } 123 | } 124 | 125 | // Step 1c 126 | re = /^(.+?)y$/; 127 | if (re.test(w)) { 128 | var fp = re.exec(w); 129 | stem = fp[1]; 130 | re = new RegExp(s_v); 131 | if (re.test(stem)) 132 | w = stem + "i"; 133 | } 134 | 135 | // Step 2 136 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 137 | if (re.test(w)) { 138 | var fp = re.exec(w); 139 | stem = fp[1]; 140 | suffix = fp[2]; 141 | re = new RegExp(mgr0); 142 | if (re.test(stem)) 143 | w = stem + step2list[suffix]; 144 | } 145 | 146 | // Step 3 147 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 148 | if (re.test(w)) { 149 | var fp = re.exec(w); 150 | stem = fp[1]; 151 | suffix = fp[2]; 152 | re = new RegExp(mgr0); 153 | if (re.test(stem)) 154 | w = stem + step3list[suffix]; 155 | } 156 | 157 | // Step 4 158 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 159 | re2 = /^(.+?)(s|t)(ion)$/; 160 | if (re.test(w)) { 161 | var fp = re.exec(w); 162 | stem = fp[1]; 163 | re = new RegExp(mgr1); 164 | if (re.test(stem)) 165 | w = stem; 166 | } 167 | else if (re2.test(w)) { 168 | var fp = re2.exec(w); 169 | stem = fp[1] + fp[2]; 170 | re2 = new RegExp(mgr1); 171 | if (re2.test(stem)) 172 | w = stem; 173 | } 174 | 175 | // Step 5 176 | re = /^(.+?)e$/; 177 | if (re.test(w)) { 178 | var fp = re.exec(w); 179 | stem = fp[1]; 180 | re = new RegExp(mgr1); 181 | re2 = new RegExp(meq1); 182 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 183 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 184 | w = stem; 185 | } 186 | re = /ll$/; 187 | re2 = new RegExp(mgr1); 188 | if (re.test(w) && re2.test(w)) { 189 | re = /.$/; 190 | w = w.replace(re,""); 191 | } 192 | 193 | // and turn initial Y back to y 194 | if (firstch == "y") 195 | w = firstch.toLowerCase() + w.substr(1); 196 | return w; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /_test/test3_simple/fifo/FIFO.pyh: -------------------------------------------------------------------------------- 1 | from pyhgl.logic import * 2 | from pyhgl.tester import tester, utils 3 | 4 | import random 5 | import time 6 | 7 | @conf Global: 8 | conf.timing = Bundle( 9 | timescale = '1ns', 10 | clk1 = {'low':20, 'high':20, 'phase':0}, 11 | clk2 = {'low':40, 'high':40, 'phase':10}, 12 | ) 13 | 14 | 15 | def binary2gray(x): 16 | return (x >> 1) ^ x 17 | 18 | 19 | @module Async_FIFO(data_width: int = 16, addr_width: int = 3): 20 | 21 | io = Bundle( 22 | w_clk = Input('0'), 23 | w_rst_n = Input('0'), 24 | w_en = Input('0'), 25 | w_data = Input(UInt[data_width](0)), 26 | full = Output('0'), 27 | 28 | r_clk = Input('0'), 29 | r_rst_n = Input('0'), 30 | r_en = Input('0') , 31 | r_data = Output(UInt[data_width](0)), 32 | empty = Output('0'), 33 | ) 34 | 35 | RAM_t = UInt[data_width] * (1 << addr_width) 36 | w_domain = ClockDomain(clock=(io.w_clk, 1), reset=(io.w_rst_n, 0)) 37 | r_domain = ClockDomain(clock=(io.r_clk, 1), reset=(io.r_rst_n, 0)) 38 | 39 | # reg 40 | with w_domain: 41 | w_ptr = Reg(UInt[addr_width+1](0)) 42 | w_ptr_gray = binary2gray(w_ptr) 43 | RAM = Reg(RAM_t(0)) 44 | with r_domain: 45 | w_ptr_gray_syncr = RegNext(RegNext(w_ptr_gray)) 46 | r_ptr = Reg(UInt[addr_width+1](0)) 47 | r_ptr_gray = binary2gray(r_ptr) 48 | Reg(io.r_data) 49 | with w_domain: 50 | r_ptr_gray_syncw = RegNext(RegNext(r_ptr_gray)) 51 | 52 | io.full <== Cat(r_ptr_gray_syncw[:-2], ~r_ptr_gray_syncw[-2:]) == w_ptr_gray 53 | io.empty <== w_ptr_gray_syncr == r_ptr_gray 54 | 55 | when io.w_en && !io.full: 56 | w_ptr <== w_ptr + 1 57 | RAM[w_ptr[:-1]] <== io.w_data 58 | when io.r_en && !io.empty: 59 | r_ptr <== r_ptr + 1 60 | io.r_data <== RAM[r_ptr[:-1]] 61 | r_ptr_1 = r_ptr[:-1] 62 | r_data_test = RAM[r_ptr_1] 63 | 64 | 65 | 66 | #--------------------------------- test ---------------------------------------- 67 | 68 | DWIDTH = 8 69 | AWIDTH = 4 70 | N = 200 71 | 72 | # random.seed(42) 73 | # write_data = [] 74 | # read_data = [] 75 | 76 | # def write_fifo(dut): 77 | # clk = negedge(dut.io.w_clk) 78 | # yield from clk 79 | # for _ in range(N): 80 | # if random.randint(0,1) and getv(dut.io.full) == 0: 81 | # setv(dut.io.w_en, 1) 82 | # v = setr(dut.io.w_data) 83 | # write_data.append(v) 84 | # else: 85 | # setv(dut.io.w_en, 0) 86 | # yield from clk 87 | 88 | # def read_fifo(dut): 89 | # clk = negedge(dut.io.r_clk) 90 | # yield from clk 91 | # for _ in range(N): 92 | # if random.randint(0,1) and getv(dut.io.empty) == 0: 93 | # setv(dut.io.r_en, 1) 94 | # yield from clk 95 | # read_data.append(getv(dut.io.r_data)) 96 | # else: 97 | # setv(dut.io.r_en, 0) 98 | # yield from clk 99 | 100 | 101 | @task write_fifo(self, dut, data, N): 102 | for _ in range(N): 103 | if getv(dut.io.full) == 0: 104 | setv(dut.io.w_en, 1) 105 | data.append(setr(dut.io.w_data)) 106 | else: 107 | setv(dut.io.w_en, 0) 108 | yield self.edge(dut.io.w_clk, 0) 109 | 110 | @task read_fifo(self, dut, data, N): 111 | for _ in range(N): 112 | if getv(dut.io.empty) == 0: 113 | setv(dut.io.r_en, 1) 114 | yield self.edge(dut.io.r_clk, 0) 115 | data.append(getv(dut.io.r_data)) 116 | else: 117 | setv(dut.io.r_en, 0) 118 | yield self.edge(dut.io.r_clk, 0) 119 | 120 | @task test_fifo(self, dut, N): 121 | yield 10 122 | setv(dut.io.r_rst_n, 1) 123 | setv(dut.io.w_rst_n, 1) 124 | write_data, read_data = [], [] 125 | yield self.join( 126 | write_fifo(dut, write_data, N), 127 | read_fifo(dut, read_data, N), 128 | ) 129 | for w, r in zip(write_data, read_data): 130 | self.AssertEq(w, r) 131 | 132 | @tester test_FIFO(self): 133 | sess = Session(Global()) 134 | sess.enter() 135 | 136 | dut = Async_FIFO(DWIDTH, AWIDTH) 137 | dut.io.w_clk <== Clock(id='clk1') 138 | dut.io.r_clk <== Clock(id='clk2') 139 | 140 | sess.track(dut) 141 | sess.join(test_fifo(dut, N)) 142 | # sess.task(write_fifo(dut), read_fifo(dut)) 143 | 144 | # sess.step(100) 145 | # setv(dut.io.r_rst_n, 1) 146 | # setv(dut.io.w_rst_n, 1) 147 | # sess.step(N * 100) 148 | 149 | # for i, o in zip(write_data, read_data): 150 | # self.EQ += i, o 151 | 152 | 153 | # @blackbox testbench(builder): 154 | # dut_name = builder.get_name(dut) 155 | # w_rst = builder.get_name(dut.io.w_rst_n) 156 | # r_rst = builder.get_name(dut.io.r_rst_n) 157 | # w_en = builder.get_name(dut.io.w_en) 158 | # r_en = builder.get_name(dut.io.r_en) 159 | # w_data = builder.get_name(dut.io.w_data) 160 | 161 | # builder.append('initial begin') 162 | # builder.append(f'$dumpfile("FIFO_iverilog.vcd");') 163 | # builder.append(f'$dumpvars(0, {dut_name});') 164 | # builder.append(f'{w_rst}=0;{r_rst}=0;#100;') 165 | # builder.append(f'{w_rst}=1;{r_rst}=1;{w_en}=1;{r_en}=1;') 166 | # for v in write_data: 167 | # builder.append(f'{w_data} = {v}; #100;') 168 | # builder.append('#200;') 169 | # builder.append('$finish;') 170 | # builder.append('end') 171 | 172 | sess.dumpVerilog('FIFO.sv', delay=True, top = True) 173 | 174 | sess.dumpVCD('FIFO.vcd') 175 | sess.dumpGraph('FIFO.gv') 176 | print(sess) 177 | # sess.test_iverilog() 178 | sess.exit() 179 | -------------------------------------------------------------------------------- /_test/test0_grammar/grammar.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | # ==================================== test grammar ======================================= 4 | from pyhgl.parser import hgl_compile, ast_dump 5 | from pyhgl.tester import tester 6 | 7 | r = [] 8 | 9 | # ==================================== expr ======================================= 10 | # priority: python `==` > `>>>` > `&&` > `||` > `|->` > python `and` 11 | 12 | # priority: same as ~ 13 | def __hgl_logicnot__(a): 14 | ret = f'! {a}' 15 | r.append(ret) 16 | return ret 17 | 18 | # priority: between `not/and/or` and `comparation` 19 | def __hgl_imply__(a,b): 20 | ret = f'{a} |-> {b}' 21 | r.append(ret) 22 | return ret 23 | 24 | # priority: above |-> 25 | def __hgl_logicor__(a,b): 26 | ret = f'{a} || {b}' 27 | r.append(ret) 28 | return ret 29 | 30 | # priority: above || 31 | def __hgl_logicand__(a,b): 32 | ret = f'{a} && {b}' 33 | r.append(ret) 34 | return ret 35 | 36 | # priority: above && 37 | def __hgl_rshift__(*args): 38 | if len(args) == 2: 39 | a, b = args 40 | ret = f'{a} >>> {b}' 41 | else: 42 | ret = f'>>> {args[0]}' 43 | r.append(ret) 44 | return ret 45 | 46 | 47 | 48 | def __hgl_unit__(a,b): 49 | ret = f'{a}`{type(b)}' 50 | r.append(ret) 51 | return ret 52 | 53 | @tester 54 | def test_expr(self): 55 | exec(hgl_compile("!'a' >>> 'b'*3 || 'd' >>> !'e' + 'f' >>> 'g'")) 56 | self.EQ += r, [ 57 | '! a', 58 | '! a >>> bbb', 59 | '! e', 60 | 'd >>> ! ef', 61 | 'd >>> ! ef >>> g', 62 | '! a >>> bbb || d >>> ! ef >>> g' 63 | ] 64 | r.clear() 65 | exec(hgl_compile(">>> 'a' >>> ('b' || 'c') && 'd' |-> 'x'*2 >>> 2e-2`m/s` != 1 |-> (2+2j)`N*m`")) 66 | self.EQ += r, [ 67 | '>>> a', 68 | 'b || c', 69 | '>>> a >>> b || c', 70 | '>>> a >>> b || c && d', 71 | "0.02`TODO
133 |