From ebc69311cf7315daf6594bf98e4dcec0b4ec696f Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Mon, 27 Jan 2020 09:31:06 -0800 Subject: [PATCH 1/5] dev: add extract-ctags.go A tool to partly automate seeding basic intel support, by parsing universal-ctags output for supported languages. A human must vet the output since ctags does not have enough data to infer comment style or derive applicable filtering rules. --- tools/extract-ctags.go | 190 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tools/extract-ctags.go diff --git a/tools/extract-ctags.go b/tools/extract-ctags.go new file mode 100644 index 000000000..046fb4506 --- /dev/null +++ b/tools/extract-ctags.go @@ -0,0 +1,190 @@ +// Program extract-ctags extracts a list of languages and filename extensions +// by parsing the output of the universal-ctags command-line tool. +// +// Basic usage: +// go run extract-ctags.go -all +// +// Output is written to stdout and consists of a block of handler arguments in +// the style expected by languages.ts. The output should be correctly formatted +// but must be vetted by a human before checking it in. +package main + +import ( + "errors" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "sort" + "strings" + "text/template" +) + +// This block should express a LanguageSpec, see the languageSpecs const in +// languages.ts for the expected format of the output. +const templateSrc = ` { + handlerArgs: { + languageID: {{quoted .ID}}, + fileExts: [{{range .Extensions}} + {{quoted .}},{{end}} + ], + commentStyle: cStyle, + }, + stylized: {{quoted .Name}}, + }, +` + +var ( + ctagsPath = flag.String("ctags", "", `Path of universal-ctags tool ("" uses $PATH)`) + langFile = flag.String("existing", "", "Path of existing languages file (.ts)") + doAll = flag.Bool("all", false, "Generate all available languages, modulo filter") + + filterBy = regexp.MustCompile(`stylized: +'(.*?)',?`) + + output = template.Must(template.New("lang").Funcs(template.FuncMap{ + "quoted": func(s string) string { + return "'" + strings.ReplaceAll(s, "'", "\\'") + "'" + }, + }).Parse(templateSrc)) +) + +func init() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, `Usage: %s [options] lang-name... + +Extract language information from universal-ctags and print a skeletal +LanguageSpec value for each to stdout in the format consumed by languages.ts. + +You must either specify language labels to extract, or -all to list all +available languages supported by the universal-ctags binary. + +If -existing is specified, the tool scans that file for languages that appear +already to be implemented, and filters them from the output. This is useful +in conjunction with -all. + +Options: +`, filepath.Base(os.Args[0])) + flag.PrintDefaults() + } +} + +func main() { + flag.Parse() + if flag.NArg() == 0 && !*doAll { + log.Fatal("You must specify languages to generate, or -all") + } + + langs, err := listMapExtensions() + if err != nil { + log.Fatalf("Parsing language extensions: %v", err) + } + exists, err := knownLanguages(*langFile) + if err != nil { + log.Fatalf("Reading known languages: %v", err) + } + for _, lang := range langs { + if !wantLang(lang.Name) { + continue + } else if exists[lang.Name] { + log.Printf("Skipped existing language: %s", lang.Name) + continue + } + if err := output.Execute(os.Stdout, lang); err != nil { + log.Fatalf("Generating output for language %q: %v", lang.Name, err) + } + } +} + +func wantLang(name string) bool { + for _, lang := range flag.Args() { + if lang == name { + return true + } + } + return *doAll +} + +type langInfo struct { + Name string + Extensions []string // ordered lexicographically +} + +// Return the expected language ID for the specified language. +func (li langInfo) ID() string { return strings.ToLower(li.Name) } + +// listMapExtensions returns an ordered, deduplicated slice of language file +// extension mappings, parsed from the output of the universal-ctags tool. +func listMapExtensions() ([]langInfo, error) { + tool := *ctagsPath + if tool == "" { + tool = "universal-ctags" + } + out, err := exec.Command(tool, "--machinable", "--list-map-extensions").Output() + if err != nil { + // For process errors, report stderr so the user can tell if they pointed + // to an invalid ctags binary, or if it's not installed. + if e, ok := err.(*exec.ExitError); ok { + err = errors.New(string(e.Stderr)) + } + return nil, fmt.Errorf("running universal-ctags: %v", err) + } + + // Eacn line of output is two tab-separated fields, language name and a bare + // file extension ("go" rather than ".go"). + db := make(map[string]map[string]bool) + lines := strings.Split(strings.TrimSpace(string(out)), "\n") + for i, line := range lines { + if strings.HasPrefix(line, "#") { + continue // comment + } + fields := strings.Fields(line) + if len(fields) != 2 { + log.Printf("Warning: line %d is malformed (%q)", i+1, line) + continue // ignore + } + + lang, ext := fields[0], fields[1] + if db[lang] == nil { + db[lang] = map[string]bool{ext: true} + } else { + db[lang][ext] = true + } + } + + // Order languages by name, and extensions lexicographically. + var result []langInfo + for name, exts := range db { + lang := langInfo{Name: name} + for ext := range exts { + lang.Extensions = append(lang.Extensions, ext) + } + sort.Strings(lang.Extensions) + result = append(result, lang) + } + sort.Slice(result, func(i, j int) bool { + return result[i].Name < result[j].Name + }) + return result, nil +} + +// knownLanguages lists the known languages from the specified implementation +// source. It returns nil without error if no file was specified. +func knownLanguages(path string) (map[string]bool, error) { + if path == "" { + return nil, nil // OK, don't filter + } + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + m := filterBy.FindAllStringSubmatch(string(data), -1) + exists := make(map[string]bool) + for _, match := range m { + exists[match[1]] = true + } + return exists, nil +} From 3fd69569f953f81716d9122ba46df616773d3c29 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Mon, 27 Jan 2020 13:04:44 -0800 Subject: [PATCH 2/5] languages: add Pascal, Verilog, and VHDL Fold together Verilog and SystemVerilog since the syntax is the same. --- languages.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/languages.ts b/languages.ts index 69dd63602..5ea5647c4 100644 --- a/languages.ts +++ b/languages.ts @@ -552,4 +552,38 @@ export const languageSpecs: LanguageSpec[] = [ }, stylized: 'R', }, + { + handlerArgs: { + languageID: 'pascal', + fileExts: ['p', 'pas', 'pp'], + commentStyle: { + // Traditional: (* this is a comment *) + // Customary: { this is also a comment } + block: { + startRegex: /(\{|\(\*)\s?/, + endRegex: /(\}|\*\))/, + }, + + // TODO: Some Pascal implementations support //-comments too. + // Is that common enough to support here? + }, + }, + stylized: 'Pascal', + }, + { + handlerArgs: { + languageID: 'verilog', + fileExts: ['sv', 'svh', 'svi', 'v'], + commentStyle: cStyle, + }, + stylized: 'Verilog', + }, + { + handlerArgs: { + languageID: 'vhdl', + fileExts: ['vhd', 'vhdl'], + commentStyle: { lineRegex: /--+\s?/ }, + }, + stylized: 'VHDL', + }, ] From b0956aceb61601d1b68ec924a50cc23f5564bcef Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Mon, 27 Jan 2020 16:10:19 -0800 Subject: [PATCH 3/5] samples: add a Pascal source sample --- samples/pascal.pas | 676 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 676 insertions(+) create mode 100644 samples/pascal.pas diff --git a/samples/pascal.pas b/samples/pascal.pas new file mode 100644 index 000000000..f2b21cec0 --- /dev/null +++ b/samples/pascal.pas @@ -0,0 +1,676 @@ +unit bzip2; +{**************************************************************************** + + BZIP2 decompression unit + + Copyright (C) 2002 by Daniel Mantione + +This unit provides a decompression stream to decode .bz2 files. It is +inpired by Julian R. Seward's libbzip2 library and therefore you should +send credits to him and bug reports to me :) + +This code is licensed under the same terms as the original libbz2 library, +which is decsribed in the file LICENSE. If you don't have this file, look +at http://www.freepascal.org for this bzip2 unit, the LICENSE file will +be included. In case of problems, contact the author. + +E-mail addresses: + +Daniel Mantione +Julian R. Seward + +Please do not contact Julian about this Pascal library, he didn't wrote it. + +****************************************************************************} +interface + +{$goto on} + +uses objects, bzip2comn; + +Type + Tbzip2_decode_stream=object(Tstream) + short:cardinal; + readstream:Pstream; + block_randomized:boolean; + blocksize:byte; + tt:Pcardinal_array; + tt_count:cardinal; + rle_run_left,rle_run_data:byte; + nextrle:Pbyte; + decode_available:cardinal; + block_origin:cardinal; + current_block:cardinal; + read_data,bits_available:byte; + inuse16:set of 0..15; + inuse:set of 0..255; + inuse_count:cardinal; + seq_to_unseq:array[0..255] of byte; + alphasize:cardinal; + group_count,group_pos,gsel,gminlen:byte; + group_no:cardinal; + glimit,gperm,gbase:Phuffarray; + selector_count:cardinal; + selector,selector_mtf:array[0..max_selectors] of byte; + len:array[0..max_groups,0..max_alpha_size] of byte; + limit:array[0..max_groups,0..max_alpha_size] of cardinal; + base:array[0..max_groups,0..max_alpha_size] of cardinal; + perm:array[0..max_groups,0..max_alpha_size] of cardinal; + minlens:array[0..max_groups] of byte; + cftab:array[0..257] of cardinal; + mtfbase:array[0..256 div mtfl_size-1] of cardinal; + mtfa:array[0..mtfa_size-1] of byte; + constructor init(Areadstream:Pstream); + function get_bits(n:byte):byte; + function get_boolean:boolean; + function get_byte:byte; + function get_cardinal24:cardinal; + function get_cardinal:cardinal; + procedure receive_mapping_table; + procedure receive_selectors; + procedure undo_mtf_values; + procedure receive_coding_tables; + procedure make_hufftab; + procedure init_mtf; + function get_mtf_value:cardinal; + procedure move_mtf_block; + procedure receive_mtf_values; + procedure detransform; + function decode_block:boolean; + procedure read(var buf;count:Longint);virtual; + procedure new_block; + procedure consume_rle;inline; + procedure rle_read(bufptr:Pbyte;var count:Longint); + destructor done;virtual; + end; + + +implementation + +{$ifdef cpui386} + {$i bzip2i386.inc} +{$endif} + +{***************************************************************************** + Tbzip2_decode_stream +*****************************************************************************} + +constructor Tbzip2_decode_stream.init(Areadstream:Pstream); + +var magic:array[1..3] of char; + c:char; + +begin + readstream:=Areadstream; + {Read the magic.} + readstream^.read(magic,sizeof(magic)); + if magic<>bzip2_stream_magic then + begin + error(stiniterror,bzip2_bad_header_magic); + exit; + end; + {Read the block size and allocate the working array.} + readstream^.read(c,1); + blocksize:=byte(c)-byte('0'); + getmem(tt,blocksize*100000*sizeof(cardinal)); + decode_available:=high(decode_available); +end; + +function Tbzip2_decode_stream.get_bits(n:byte):byte; + +var data:byte; + +begin + if n>bits_available then + begin + readstream^.read(data,1); + get_bits:=(read_data shr (8-n)) or data shr (8-(n-bits_available)); + read_data:=data shl (n-bits_available); + inc(bits_available,8); + end + else + begin + get_bits:=read_data shr (8-n); + read_data:=read_data shl n; + end; + dec(bits_available,n); +end; + +function Tbzip2_decode_stream.get_boolean:boolean; + +begin + get_boolean:=boolean(get_bits(1)); +end; + +function Tbzip2_decode_stream.get_byte:byte; + +begin + get_byte:=get_bits(8); +end; + +function Tbzip2_decode_stream.get_cardinal24:cardinal; + +begin + get_cardinal24:=get_bits(8) shl 16 or get_bits(8) shl 8 or get_bits(8); +end; + + +function Tbzip2_decode_stream.get_cardinal:cardinal; + +begin + get_cardinal:=get_bits(8) shl 24 or get_bits(8) shl 16 or get_bits(8) shl 8 or + get_bits(8); +end; + +procedure Tbzip2_decode_stream.receive_mapping_table; + +{Receive the mapping table. To save space, the inuse set is stored in pieces + of 16 bits. First 16 bits are stored which pieces of 16 bits are used, then + the pieces follow.} + +var i,j:byte; + +begin + inuse16:=[]; + {Receive the first 16 bits which tell which pieces are stored.} + for i:=0 to 15 do + if get_boolean then + include(inuse16,i); + + {Receive the used pieces.} + inuse:=[]; + inuse_count:=0; + for i:=0 to 15 do + if i in inuse16 then + for j:=0 to 15 do + if get_boolean then + begin + include(inuse,16*i+j); + seq_to_unseq[inuse_count]:=16*i+j; + inc(inuse_count); + end; +{ system.write('Mapping table: '); + for i:=0 to 255 do + if i in inuse then + system.write(i,' '); + writeln;} +end; + +procedure Tbzip2_decode_stream.receive_selectors; + +{Receives the selectors.} + +var i:cardinal; + j:byte; + +begin + group_count:=get_bits(3); + selector_count:=get_bits(8) shl 7 or get_bits(7); + for i:=0 to selector_count-1 do + begin + j:=0; + while get_boolean do + begin + inc(j); + if j>5 then + error(streaderror,bzip2_data_error); + end; + selector_mtf[i]:=j; + end; +{ system.write('Selector_mtf: '); + for i:=0 to selector_count-1 do + system.write(selector_mtf[i],' '); + writeln;} +end; + +procedure Tbzip2_decode_stream.undo_mtf_values; + +{Undo the MTF values for the selectors.} + +var pos:array[0..max_groups] of byte; + i:cardinal; + v,tmp:byte; + +begin + for v:=0 to group_count-1 do + pos[v]:=v; + for i:=0 to selector_count-1 do + begin + v:=selector_mtf[i]; + tmp:=pos[v]; + while v<>0 do + begin + pos[v]:=pos[v-1]; + dec(v); + end; + pos[0]:=tmp; + selector[i]:=tmp; + end; +end; + +procedure Tbzip2_decode_stream.receive_coding_tables; + +var t,curr:byte; + i:cardinal; + +begin + for t:=0 to group_count-1 do + begin + curr:=get_bits(5); + for i:=0 to alphasize-1 do + begin + repeat + if not(curr in [1..20]) then + begin + error(streaderror,bzip2_data_error); + exit; + end; + if not get_boolean then + break; + if get_boolean then + dec(curr) + else + inc(curr); + until false; + len[t,i]:=curr; + end; + end; +{ writeln('Coding tables:'); + for t:=0 to group_count-1 do + begin + for i:=0 to alphasize-1 do + system.write(len[t,i],' '); + writeln; + end;} +end; + +procedure Tbzip2_decode_stream.make_hufftab; + +{Builds the Huffman tables.} + +var i:cardinal; + t,minlen,maxlen:byte; + +begin + for t:=0 to group_count-1 do + begin + minlen:=32; + maxlen:=0; + for i:=0 to alphasize-1 do + begin + if len[t,i]>maxlen then + maxlen:=len[t,i]; + if len[t,i]glimit^[zn] do + begin + inc(zn); + zvec:=zvec shl 1 or byte(get_boolean); + end; + get_mtf_value:=gperm^[zvec-gbase^[zn]]; +end; + +procedure Tbzip2_decode_stream.move_mtf_block; + +var i:byte; + j,k:cardinal; + +begin + k:=MTFA_SIZE; + for i:=256 div MTFL_SIZE-1 downto 0 do + begin + j:=mtfbase[i]; + Pcardinal(@mtfa[k- 4])^:=Pcardinal(@mtfa[j+12])^; + Pcardinal(@mtfa[k- 8])^:=Pcardinal(@mtfa[j+ 8])^; + Pcardinal(@mtfa[k-12])^:=Pcardinal(@mtfa[j+ 4])^; + dec(k,16); + Pcardinal(@mtfa[k ])^:=Pcardinal(@mtfa[j ])^; + mtfbase[i]:=k; + end; +end; + +procedure Tbzip2_decode_stream.receive_mtf_values; + +const run_a=0; + run_b=1; + +var t,next_sym:cardinal; + es:cardinal; + n:byte; + nn,i:cardinal; + p,q:Pbyte; + u,v:Pcardinal; + lno,off:cardinal; + +begin + group_no:=high(group_no); + group_pos:=0; + t:=0; + for i:=0 to 257 do + cftab[i]:=0; + init_mtf; + next_sym:=get_mtf_value; + while next_sym<>inuse_count+1 do + begin +{ writeln(t,' ',next_sym); + if t=22296 then + t:=t; } + if next_sym<=run_b then + begin + es:=0; + n:=0; + repeat + inc(es,(next_sym+1) shl n); + inc(n); + next_sym:=get_mtf_value; + until next_sym>run_b; + n:=seq_to_unseq[mtfa[mtfbase[0]]]; + inc(cftab[n],es); + if t+es>100000*blocksize then + begin + error(streaderror,bzip2_data_error); + exit; + end; + while es>0 do + begin + tt^[t]:=ntole(cardinal(n)); + dec(es); + inc(t); + end; + end + else + begin + nn:=next_sym-1; + if nnp) do + begin + q^:=(q-1)^; + dec(q); + end; + u:=@mtfbase; + v:=u+lno; + repeat + mtfa[v^]:=mtfa[(v-1)^+MTFL_SIZE-1]; + dec(v); + dec(v^); + until v=u; + mtfa[v^]:=n; + if v^=0 then + move_mtf_block; + end; + inc(cftab[seq_to_unseq[n]]); + tt^[t]:=ntole(cardinal(seq_to_unseq[n])); + inc(t); + if t>100000*blocksize then + begin + error(streaderror,bzip2_data_error); + exit; + end; + next_sym:=get_mtf_value; + end; + end; + tt_count:=t; + {Setup cftab to facilitate generation of T^(-1).} + t:=0; + for i:=0 to 256 do + begin + nn:=cftab[i]; + cftab[i]:=t; +{ writeln(i,' ',t);} + inc(t,nn); + end; +end; + +{$ifndef HAVE_DETRANSFORM} + +procedure Tbzip2_decode_stream.detransform; + +var a:cardinal; + p,q,r:Pcardinal; + +begin + a:=0; + p:=@tt^[0]; + q:=p+tt_count; + while p<>q do + begin + r:=@tt^[cftab[ntole(p^) and $ff]]; + inc(cftab[ntole(p^) and $ff]); + r^:=r^ or ntole(a); + inc(a,256); + inc(p); + end; +end; + +{$endif} + +function Tbzip2_decode_stream.decode_block:boolean; + +{Decode a new compressed block.} + +var magic:array[1..6] of char; + stored_blockcrc:cardinal; + i:byte; + +begin + for i:=1 to 6 do + magic[i]:=char(get_byte); + if magic='1AY&SY' then + begin + inc(current_block); +{ writeln('Block ',current_block,': Header ok');} + stored_blockcrc:=get_cardinal; + block_randomized:=get_boolean; + block_origin:=get_cardinal24; + + {Receive the mapping table.} + receive_mapping_table; + alphasize:=cardinal(inuse_count)+2; +{ writeln('Mapping table ok.');} + + {Receive the selectors.} + receive_selectors; + if status<>0 then + exit; +{ writeln('Selectors ok.');} + {Undo the MTF values for the selectors.} + undo_mtf_values; +{ writeln('Undo mtf ok.');} + {Receive the coding tables.} + receive_coding_tables; + if status<>0 then + exit; +{ writeln('Coding tables ok');} + {Build the Huffman tables.} + make_hufftab; +{ writeln('Huffman ok.');} + {Receive the MTF values.} + receive_mtf_values; +{ writeln('MTF OK');} + {Undo the Burrows Wheeler transformation.} + detransform; +{ writeln('Detransform OK');} + decode_available:=tt_count; + end + else + begin + if magic<>#$17'rE8P'#$90 then + error(streaderror,bzip2_bad_block_magic); + decode_block:=false; + end; +end; + +procedure Tbzip2_decode_stream.new_block; + +begin + if decode_block then + nextrle:=@tt^[ntole(tt^[block_origin]) shr 8] + else + begin + error(streaderror,bzip2_endoffile); + nextrle:=nil; + end; +end; + +procedure Tbzip2_decode_stream.consume_rle;inline; + +{Make nextrle point to the next decoded byte. If nextrle did point to the last + byte in the current block, decode the next block.} + +begin +{ Pcardinal(nextrle)^:=Pcardinal(nextrle)^ shr 8;} + nextrle:=@tt^[ntole(Pcardinal(nextrle)^) shr 8]; + dec(decode_available); + if decode_available=0 then + new_block; +end; + +procedure Tbzip2_decode_stream.rle_read(bufptr:Pbyte;var count:Longint); + +var rle_len:cardinal; + data:byte; + +label rle_write; + +begin + rle_len:=rle_run_left; + data:=rle_run_data; + if block_randomized then + {Not yet implemented.} + runerror(212) + else + begin + if rle_len<>0 then + {Speed is important. Instead of an if statement within the + repeat loop use a goto outside the loop.} + goto rle_write; + repeat + if decode_available=0 then + break; + rle_len:=1; + data:=nextrle^; + consume_rle; + if (decode_available>0) and (data=nextrle^) then + begin + inc(rle_len); + consume_rle; + if (decode_available>0) and (data=nextrle^) then + begin + inc(rle_len); + consume_rle; + if (decode_available>0) and (data=nextrle^) then + begin + consume_rle; + inc(rle_len,nextrle^+1); + consume_rle; + end; + end; + end; +rle_write: + repeat + bufptr^:=data; + inc(bufptr); + dec(count); + dec(rle_len); + until (rle_len=0) or (count=0); + until count=0; + short:=count; + end; + rle_run_data:=data; + rle_run_left:=rle_len; +end; + +procedure Tbzip2_decode_stream.read(var buf;count:Longint); + +var bufptr:Pbyte; + +begin + short:=0; + bufptr:=@buf; + if decode_available=high(decode_available) then + begin + {Initialize the rle process: + - Decode a block + - Initialize pointer.} + if not decode_block then + begin + error(streaderror,bzip2_endoffile); + nextrle:=nil; + end; + nextrle:=@tt^[ntole(tt^[block_origin]) shr 8]; + end; + rle_read(bufptr,count); +end; + +destructor Tbzip2_decode_stream.done; + +begin + if tt<>nil then + freemem(tt,blocksize*100000*sizeof(cardinal)); + inherited done; +end; + +end. From 772b186ceac283cd3b2745ee2def3c1260ce2eed Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Tue, 28 Jan 2020 09:46:07 -0800 Subject: [PATCH 4/5] samples: add a Verilog source sample --- samples/verilog.v | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 samples/verilog.v diff --git a/samples/verilog.v b/samples/verilog.v new file mode 100644 index 000000000..f209c446a --- /dev/null +++ b/samples/verilog.v @@ -0,0 +1,154 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: helloworld.v +// +// Project: wbuart32, a full featured UART with simulator +// +// Purpose: To create a *very* simple UART test program, which can be used +// as the top level design file of any FPGA program. +// +// With some modifications (discussed below), this RTL should be able to +// run as a top-level testing file, requiring only the UART and clock pin +// to work. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2015-2016, Gisselquist Technology, LLC +// +// This program is free software (firmware): you can redistribute it and/or +// modify it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. (It's in the $(ROOT)/doc directory, run make with no +// target there if the PDF file isn't present.) If not, see +// for a copy. +// +// License: GPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/gpl.html +// +// +//////////////////////////////////////////////////////////////////////////////// +// +// +// One issue with the design is how to set the values of the setup register. +// (*This is a comment, not a verilator attribute ... ) Verilator needs to +// know/set those values in order to work. However, this design can also be +// used as a stand-alone top level configuration file. In this latter case, +// the setup register needs to be set internal to the file. Here, we use +// OPT_STANDALONE to distinguish between the two. If set, the file runs under +// (* Another comment still ...) Verilator and we need to get i_setup from the +// external environment. If not, it must be set internally. +// +`ifndef VERILATOR +`define OPT_STANDALONE +`endif +// +// +// Two versions of the UART can be found in the rtl directory: a full featured +// UART, and a LITE UART that only handles 8N1 -- no break sending, break +// detection, parity error detection, etc. If we set USE_LITE_UART here, those +// simplified UART modules will be used. +// +// `define USE_LITE_UART +// +// +module helloworld(i_clk, +`ifndef OPT_STANDALONE + i_setup, +`endif + o_uart_tx); + input i_clk; + output wire o_uart_tx; + + // Here we set i_setup to something appropriate to create a 115200 Baud + // UART system from a 100MHz clock. This also sets us to an 8-bit data + // word, 1-stop bit, and no parity. This will be overwritten by + // i_setup, but at least it gives us something to start with/from. + parameter INITIAL_UART_SETUP = 31'd868; + + // The i_setup wires are input when run under Verilator, but need to + // be set internally if this is going to run as a standalone top level + // test configuration. +`ifdef OPT_STANDALONE + wire [30:0] i_setup; + assign i_setup = INITIAL_UART_SETUP; +`else + input [30:0] i_setup; +`endif + + reg pwr_reset; + initial pwr_reset = 1'b1; + always @(posedge i_clk) + pwr_reset <= 1'b0; + + reg [7:0] message [0:15]; + + initial begin + message[ 0] = "H"; + message[ 1] = "e"; + message[ 2] = "l"; + message[ 3] = "l"; + message[ 4] = "o"; + message[ 5] = ","; + message[ 6] = " "; + message[ 7] = "W"; + message[ 8] = "o"; + message[ 9] = "r"; + message[10] = "l"; + message[11] = "d"; + message[12] = "!"; + message[13] = " "; + message[14] = "\r"; + message[15] = "\n"; + end + + reg [27:0] counter; + initial counter = 28'hffffff0; + always @(posedge i_clk) + counter <= counter + 1'b1; + + wire tx_break, tx_busy; + reg tx_stb; + reg [3:0] tx_index; + reg [7:0] tx_data; + + assign tx_break = 1'b0; + + initial tx_index = 4'h0; + always @(posedge i_clk) + if ((tx_stb)&&(!tx_busy)) + tx_index <= tx_index + 1'b1; + always @(posedge i_clk) + tx_data <= message[tx_index]; + + initial tx_stb = 1'b0; + always @(posedge i_clk) + if (&counter) + tx_stb <= 1'b1; + else if ((tx_stb)&&(!tx_busy)&&(tx_index==4'hf)) + tx_stb <= 1'b0; + + // Bypass any hardware flow control + wire cts_n; + assign cts_n = 1'b0; + +`ifdef USE_LITE_UART + txuartlite + #(24'd868) + transmitter(i_clk, tx_stb, tx_data, o_uart_tx, tx_busy); +`else + txuart transmitter(i_clk, pwr_reset, i_setup, tx_break, + tx_stb, tx_data, cts_n, o_uart_tx, tx_busy); +`endif + +endmodule From 2c38e2e494fd6775eef0841b3f2923fc2304f1e3 Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Tue, 28 Jan 2020 09:52:29 -0800 Subject: [PATCH 5/5] samples: add a VHDL source sample --- samples/vhdl.vhd | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 samples/vhdl.vhd diff --git a/samples/vhdl.vhd b/samples/vhdl.vhd new file mode 100644 index 000000000..59f3cdca4 --- /dev/null +++ b/samples/vhdl.vhd @@ -0,0 +1,54 @@ +-- Copyright (c) 2012 Brian Nezvadovitz +-- This software is distributed under the terms of the MIT License shown below. +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to +-- deal in the Software without restriction, including without limitation the +-- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +-- sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +-- IN THE SOFTWARE. + +-- Implements a synchronous register of a given width with a load signal. + +library ieee; +use ieee.std_logic_1164.all; + +entity reg is + generic ( + WIDTH : positive := 1 + ); + port ( + clk : in std_logic; + rst : in std_logic; + load : in std_logic; + input : in std_logic_vector(WIDTH-1 downto 0); + output : out std_logic_vector(WIDTH-1 downto 0) + ); +end reg; + +architecture BHV of reg is +begin + + process(clk, rst) + begin + if(rst = '1') then + output <= (others => '0'); + elsif(rising_edge(clk)) then + if(load = '1') then + output <= input; + end if; + end if; + end process; + +end BHV;