-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathOsvvmScriptsFileCreate.tcl
More file actions
607 lines (556 loc) · 27.3 KB
/
Copy pathOsvvmScriptsFileCreate.tcl
File metadata and controls
607 lines (556 loc) · 27.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
# File Name: OsvvmScriptsFileCreate.tcl
# Purpose: Scripts for running simulations
# Revision: OSVVM MODELS STANDARD VERSION
#
# Maintainer: Jim Lewis email: jim@synthworks.com
# Contributor(s):
# Jim Lewis email: jim@synthworks.com
# Markus Ferringer Patterns for error handling and callbacks, ...
#
# Description
# Tcl procedures to Autogenerate Files
#
# Developed by:
# SynthWorks Design Inc.
# VHDL Training Classes
# OSVVM Methodology and Model Library
# 11898 SW 128th Ave. Tigard, Or 97223
# http://www.SynthWorks.com
#
# Revision History:
# Date Version Description
# 1/2025 2025.01 Initial
#
#
# This file is part of OSVVM.
#
# Copyright (c) 2025 by SynthWorks Design Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package require fileutil
namespace eval ::osvvm {
# -------------------------------------------------
# FindOsvvmSettingsDirectory
#
proc FindOsvvmSettingsDirectory {{OsvvmSubdirectory "osvvm"}} {
# When StartUpShared.tcl calls this to determine the value of ::osvvm::OsvvmUserSettingsDirectory,
# OsvvmSettingsLocal.tcl has not been run yet, as a result,
# * OsvvmSettingsSubdirectory will have its default value of "" and
# * SettingsAreRelativeToSimulationDirectory will have its default value of false.
# For OsvvmSettingsSubdirectory, this is ok as it is only needed to differentiate the VHDL code and not the settings.
# SettingsAreRelativeToSimulationDirectory this is not ok and it usage has been deprecated.
# This was used to differentiate VHDL sources for different simulators - use OsvvmSettingsSubdirectory instead
#
set SettingsRootDirectory ${::osvvm::OsvvmHomeDirectory}
if {$::osvvm::SettingsAreRelativeToSimulationDirectory} {
puts "WARNING: SettingsAreRelativeToSimulationDirectory is deprecated. Usage will generate an error in the future"
set SettingsRootDirectory [file normalize ${::osvvm::CurrentSimulationDirectory}]
}
if {$::osvvm::OsvvmSettingsDirectory ne ""} {
set SettingsDirectory $::osvvm::OsvvmSettingsDirectory
} elseif {[info exists ::env(OSVVM_SETTINGS_DIR)]} {
# Note that OSVVM_SETTINGS_DIR may be either an absolute or relative path
# For relative paths, use OsvvmHomeDirectory (location of OsvvmLibraries) as the base
set SettingsDirectory $::env(OSVVM_SETTINGS_DIR)
} elseif {[file isdirectory ${SettingsRootDirectory}/../OsvvmSettings]} {
set SettingsDirectory ../OsvvmSettings
} else {
puts "Note: Putting setting in directory OsvvmLibraries/${OsvvmSubdirectory}"
set SettingsDirectory ${OsvvmSubdirectory}
}
set SettingsDirectoryFullPath [file normalize [file join ${SettingsRootDirectory} ${SettingsDirectory} ${::osvvm::OsvvmSettingsSubdirectory}]]
CreateDirectory $SettingsDirectoryFullPath
# set RelativeSettingsDirectory [::fileutil::relative [pwd] $SettingsDirectoryFullPath]
# return $RelativeSettingsDirectory
# Needs to be a normalized path
return $SettingsDirectoryFullPath
}
# -------------------------------------------------
# CreateOsvvmScriptSettingsPkg
#
proc CreateOsvvmScriptSettingsPkg {SettingsDirectory} {
set OsvvmScriptSettingsPkgFile [file join ${SettingsDirectory} "OsvvmScriptSettingsPkg_generated.vhd"]
set NewFileName [file join ${SettingsDirectory} "OsvvmScriptSettingsPkg_new.vhd"]
set WriteCode [catch {set FileHandle [open $NewFileName w]} WriteErrMsg]
if {$WriteCode} {
puts "Not able to open OsvvmScriptSettingsPkg_generated.vhd. Using defaults instead"
return ""
}
puts $FileHandle "-- This file is autogenerated by CreateOsvvmScriptSettingsPkg"
puts $FileHandle "package body OsvvmScriptSettingsPkg is"
puts $FileHandle " constant OSVVM_HOME_DIRECTORY : string := \"[file normalize ${::osvvm::OsvvmHomeDirectory}]\" ;"
if {${::osvvm::OsvvmTempOutputDirectory} eq ""} {
puts $FileHandle " constant OSVVM_TEMP_OUTPUT_DIRECTORY : string := \"\" ;"
} else {
puts $FileHandle " constant OSVVM_TEMP_OUTPUT_DIRECTORY : string := \"${::osvvm::OsvvmTempOutputDirectory}/\" ;"
}
if {${::osvvm::OutputBaseDirectory} eq ""} {
puts $FileHandle " constant OSVVM_BASE_DIRECTORY : string := \"\" ;"
} else {
puts $FileHandle " constant OSVVM_BASE_DIRECTORY : string := \"${::osvvm::OutputBaseDirectory}/\" ;"
}
puts $FileHandle " constant OSVVM_BUILD_YAML_FILE : string := \"${::osvvm::OsvvmTempYamlFile}\" ;"
puts $FileHandle " constant OSVVM_TRANSCRIPT_YAML_FILE : string := \"${::osvvm::TempTranscriptYamlFile}\" ;"
puts $FileHandle " constant OSVVM_REVISION : string := \"${::osvvm::OsvvmVersion}\" ;"
puts $FileHandle " constant OSVVM_SETTINGS_REVISION : string := \"${::osvvm::OsvvmVersionCompatibility}\" ; -- For Settings"
puts $FileHandle " constant ALERT_YAML_VERSION : string := \"${::osvvm::OsvvmAlertYamlVersion}\" ;"
puts $FileHandle " constant SCOREBOARD_YAML_VERSION : string := \"${::osvvm::OsvvmScoreboardYamlVersion}\" ;"
puts $FileHandle " constant COVERAGE_YAML_VERSION : string := \"${::osvvm::OsvvmCoverageYamlVersion}\" ;"
puts $FileHandle " constant REQUIREMENTS_YAML_VERSION : string := \"${::osvvm::OsvvmRequirementsYamlVersion}\" ;"
puts $FileHandle "end package body OsvvmScriptSettingsPkg ;"
close $FileHandle
if {[FileDiff $OsvvmScriptSettingsPkgFile $NewFileName]} {
file rename -force $NewFileName $OsvvmScriptSettingsPkgFile
} else {
file delete -force $NewFileName
}
return $OsvvmScriptSettingsPkgFile
}
# -------------------------------------------------
# FindOsvvmScriptSettingsPkg
#
proc FindOsvvmScriptSettingsPkg { } {
set SettingsDirectory [FindOsvvmSettingsDirectory]
if {[FileExists $SettingsDirectory/OsvvmScriptSettingsPkg_local.vhd]} {
return $SettingsDirectory/OsvvmScriptSettingsPkg_local.vhd
# If SettingsDirectory is in a subdirectory for a tool and/or vendor it may be appropriate to look above to find a local "default one"
# elsif {[FileExists $SettingsDirectory/${::osvvm::ToolName}/OsvvmScriptSettingsPkg_local.vhd]} { return $SettingsDirectory/${::osvvm::ToolName}/OsvvmScriptSettingsPkg_local.vhd }
} else {
# Generate the file if possible
set GeneratedPkg [CreateOsvvmScriptSettingsPkg $SettingsDirectory]
# puts "GeneratedPkg = $GeneratedPkg"
if {[FileExists $GeneratedPkg]} {
return $GeneratedPkg
} else {
return OsvvmScriptSettingsPkg_default.vhd
}
}
}
# -------------------------------------------------
# CreatePathPkg
#
proc CreatePathPkg {BaseName {SettingsDirectory ""}} {
if {$SettingsDirectory eq ""} {set SettingsDirectory $::osvvm::OsvvmUserSettingsDirectory}
set TestSettingsPkgFile [file join ${SettingsDirectory} "${BaseName}PathPkg_generated.vhd"]
set NewFileName [file join ${SettingsDirectory} "${BaseName}PathPkg_new.vhd"]
set DefaultSettingsPkgFile [file join ${SettingsDirectory} "${BaseName}PathPkg_default.vhd"]
set WriteCode [catch {set FileHandle [open $NewFileName w]} WriteErrMsg]
if {$WriteCode} {
puts "Not able to open ${NewFileName}. Using defaults instead"
analyze ${BaseName}SettingsPkg_default.vhd
return ""
}
set LocalScriptDir "[::fileutil::relative ${::osvvm::CurrentSimulationDirectory} [file normalize ${::osvvm::CurrentWorkingDirectory}]]"
puts $FileHandle "-- This file is autogenerated by CreatePathPkg"
puts $FileHandle "package ${BaseName}SettingsPkg is"
puts $FileHandle " constant TEST_PATH_DIR : string := \"${LocalScriptDir}\" ;"
puts $FileHandle " constant TEST_PATH_SET : boolean := TRUE ;"
puts $FileHandle "end package ${BaseName}SettingsPkg ;"
close $FileHandle
if {[FileDiff $TestSettingsPkgFile $NewFileName]} {
file rename -force $NewFileName $TestSettingsPkgFile
} else {
file delete -force $NewFileName
}
analyze $TestSettingsPkgFile
return $TestSettingsPkgFile
}
# -------------------------------------------------
# CreateTestCaseCommonPkg
#
proc CreateTestCaseCommonPkg { {PackageName "TestCaseCommonPkg"} {ValidatedResults "../ValidatedResults"} } {
# set CurrentDir ""
set CurrentDir [file normalize ${::osvvm::CurrentWorkingDirectory}]
set NewFileName [file join ${CurrentDir} "NewCreateTestCaseCommonPkg.vhd"]
if {${::osvvm::OutputBaseDirectory} eq ""} {
set FileBaseName ""
} else {
set FileBaseName "_[RemoveFilePathChars ${::osvvm::OutputBaseDirectory}]"
}
if {$::osvvm::Supports2019FilePath && $::osvvm::VhdlVersion >= 2019} {
set TestCaseCommonPkgFile [file join ${CurrentDir} "${PackageName}${FileBaseName}.vhd"]
} else {
CreateDirectory [file join ${CurrentDir} deprecated]
set TestCaseCommonPkgFile [file join ${CurrentDir} "deprecated" "${PackageName}${FileBaseName}_c.vhd"]
}
if {![info exists ::osvvm::TestSuiteName]} {
error "Call TestSuite before calling CreateTestCaseCommonPkg"
return
}
set WriteCode [catch {set FileHandle [open $NewFileName w]} WriteErrMsg]
if {$WriteCode} {
puts "ScriptError: Not able to create ${TestCaseCommonPkgFile}"
} else {
puts $FileHandle "-- This file is autogenerated by CreateTestCaseCommonPkg"
puts $FileHandle "library osvvm ;"
puts $FileHandle "context osvvm.OsvvmContext ;"
puts $FileHandle "package ${PackageName} is"
if {$::osvvm::Supports2019FilePath && $::osvvm::VhdlVersion >= 2019} {
puts $FileHandle " constant PATH_TO_TEST_SRC : string := RemoveEndingSeparator(ChangeSeparator(FILE_PATH)) & \"/\"; -- only valid with VHDL-2019"
} else {
puts $FileHandle " constant PATH_TO_TEST_SRC : string := \"[file normalize [file join $::osvvm::CurrentWorkingDirectory]]/\" ;"
}
puts $FileHandle " constant PATH_TO_VALIDATED_RESULTS : string := PATH_TO_TEST_SRC & \"${ValidatedResults}/\" ;"
puts $FileHandle " constant CHECK_TRANSCRIPT : boolean := PATH_TO_TEST_SRC'length > 0 ; -- TRUE if all went well"
puts $FileHandle ""
puts $FileHandle " -- PATH_TO_RESULTS is for test case generated output other than TranscriptOpen. If used you must create it"
puts $FileHandle " constant BUILD_NAME : string := \"${::osvvm::BuildName}\" ;"
puts $FileHandle " constant TEST_SUITE_NAME : string := \"${::osvvm::TestSuiteName}\" ;"
puts $FileHandle " constant PATH_TO_RESULTS : string := OSVVM_BASE_DIRECTORY & BUILD_NAME & \"/results/\" & TEST_SUITE_NAME & \"/\" ;"
puts $FileHandle ""
puts $FileHandle " -- Deprecated. Provided for backward compatibility"
puts $FileHandle " constant RESULTS_DIR : string := PATH_TO_RESULTS ;"
puts $FileHandle " constant VALIDATED_RESULTS_DIR : string := PATH_TO_VALIDATED_RESULTS ;"
puts $FileHandle "end package ${PackageName} ;"
close $FileHandle
if {[FileDiff $TestCaseCommonPkgFile $NewFileName]} {
puts "Creating $TestCaseCommonPkgFile"
file rename -force $NewFileName $TestCaseCommonPkgFile
} else {
puts "Files $NewFileName $TestCaseCommonPkgFile match. No updates"
file delete -force $NewFileName
}
}
return $TestCaseCommonPkgFile
}
# -------------------------------------------------
# CreateAndAnalyzeBuildSettingsPkg
#
proc CreateBuildSettingsPkg {BaseName {SettingsDirectory ""}} {
if {$SettingsDirectory eq ""} {set SettingsDirectory $::osvvm::OsvvmUserSettingsDirectory}
set TestSettingsPkgFile [file join ${SettingsDirectory} "${BaseName}SettingsPkg_generated.vhd"]
set NewFileName [file join ${SettingsDirectory} "${BaseName}SettingsPkg_new.vhd"]
set DefaultSettingsPkgFile [file join ${SettingsDirectory} "${BaseName}SettingsPkg_default.vhd"]
set WriteCode [catch {set FileHandle [open $NewFileName w]} WriteErrMsg]
if {$WriteCode} {
puts "Not able to open ${NewFileName}. Using defaults instead"
analyze ${BaseName}SettingsPkg_default.vhd
return ""
}
set LocalScriptDir "[::fileutil::relative ${::osvvm::CurrentSimulationDirectory} [file normalize ${::osvvm::CurrentWorkingDirectory}]]"
puts $FileHandle "-- This file is autogenerated by CreateBuildSettingsPkg"
puts $FileHandle "package ${BaseName}SettingsPkg is"
puts $FileHandle " constant LOCAL_SCRIPT_DIR : string := \"${LocalScriptDir}\" ;"
puts $FileHandle " constant TEST_SUITE_NAME : string := \"${::osvvm::TestSuiteName}\" ;"
# Should be in top level OsvvmSettings
puts $FileHandle " constant RESULTS_DIR : string := \"${::osvvm::ResultsDirectory}\" ;"
if {$::osvvm::Debug} {
puts $FileHandle " constant MIRROR_ENABLE : boolean := TRUE ;"
} else {
puts $FileHandle " constant MIRROR_ENABLE : boolean := FALSE ;"
}
puts $FileHandle "end package ${BaseName}SettingsPkg ;"
close $FileHandle
if {[FileDiff $TestSettingsPkgFile $NewFileName]} {
file rename -force $NewFileName $TestSettingsPkgFile
} else {
file delete -force $NewFileName
}
analyze $TestSettingsPkgFile
return $TestSettingsPkgFile
}
# -------------------------------------------------
# AutoGenerateFile
# Extract from FileName everything up to and including the pattern in the string
# Write Extracted contents to NewFileName
# Example call: set ErrorCode [catch {AutoGenerateFile $FileName $NewFileName "--!! Autogenerated:"} errmsg]
proc AutoGenerateFile {FileName NewFileName AutoGenerateMarker} {
set ReadCode [catch {set ReadFile [open $FileName r]} ReadErrMsg]
if {$ReadCode} { return }
set LinesOfFile [split [read $ReadFile] \n]
close $ReadFile
set WriteCode [catch {set WriteFile [open $NewFileName w]} WriteErrMsg]
if {$WriteCode} { return }
foreach OneLine $LinesOfFile {
puts $WriteFile $OneLine
if { [regexp ${AutoGenerateMarker} $OneLine] } {
break
}
}
close $WriteFile
}
# -------------------------------------------------
# FileDiff
#
proc FileDiff {File1 File2} {
set ReadFile1Code [catch {set FileHandle1 [open $File1 r]} ReadErrMsg]
if {$ReadFile1Code} {return "true"}
set LinesOfFile1 [split [read $FileHandle1] \n]
close $FileHandle1
set LengthOfFile1 [llength $LinesOfFile1]
set ReadFile2Code [catch {set FileHandle2 [open $File2 r]} ReadErrMsg]
if {$ReadFile2Code} {return "true"}
set LinesOfFile2 [split [read $FileHandle2] \n]
close $FileHandle2
set LengthOfFile2 [llength $LinesOfFile2]
if {$LengthOfFile1 != $LengthOfFile2} {return "true"}
for {set i 0} {$i < $LengthOfFile1} {incr i} {
if {[lindex $LinesOfFile1 $i] ne [lindex $LinesOfFile2 $i]} {return "true"}
}
return "false"
}
# -------------------------------------------------
# ReadFrom - Open File and read it into the stream
#
proc ReadFrom {filename} {set f [open $filename]; return [read $f][close $f]}
# -------------------------------------------------
# PrintTo - Direct a stream of information into a file
#
proc PrintTo {filename str} {set f [open $filename w]; puts $f $str; close $f}
# -------------------------------------------------
# MakeVti - Replace FileName with FileNameVti
#
proc MakeVti {FileName FilePrefix} {
PrintTo [file join $FilePrefix Vti ${FileName}Vti_a.vhd] [regsub -all ${FileName} [ReadFrom [file join $FilePrefix ${FileName}_a.vhd]] ${FileName}Vti]
}
# -------------------------------------------------
# Make2008 - For VHDL-2008 version remove the comment "--%%UncommentFor2008 " from the file
#
proc Make2008 {FileName FilePrefix} {
PrintTo [file join $FilePrefix deprecated ${FileName}_a.vhd] [regsub -all -- "--%%UncommentFor2008 " [ReadFrom [file join $FilePrefix ${FileName}_a.vhd]] ""]
}
# -------------------------------------------------
# MakeArch - Create Vti, 2008 and Vti/2008 architectures
#
proc MakeArch {FileName} {
variable CurrentWorkingDirectory
MakeVti $FileName $CurrentWorkingDirectory
Make2008 $FileName $CurrentWorkingDirectory
Make2008 ${FileName}Vti [file join $CurrentWorkingDirectory Vti]
}
# -------------------------------------------------
# GetNewName - local
# Should be an OSVVM utility as other things do this too
#
proc GetNewName {FileName} {
#
# For FileName of the form File.ext return File_new.ext
#
set FileExtension [file extension $FileName]
set FileNameRoot [file rootname $FileName]
return ${FileNameRoot}_new${FileExtension}
}
# -------------------------------------------------
# CopyFileIfDiffOtherwiseDelete - local
# Should be an OSVVM utility as other things do this too
#
proc CopyFileIfDiffOtherwiseDelete {NewFileName FileName} {
#
# If NewFileName differs from FileName, replace FileName with NewFileName, otherwise, delete NewFileName
#
# NewFileName - New file
# FileName - File to replace if they differ
#
if {![file exists $FileName] || [FileDiff ${NewFileName} ${FileName}]} {
file rename -force ${NewFileName} ${FileName}
} else {
file delete -force ${NewFileName}
}
}
# -------------------------------------------------
# MakePkgHeader
#
proc MakePkgHeader {PkgBodyFile PkgHeaderFile} {
#
# For a package body of deferred constants, create a package header with constant declarations
#
# PkgBodyFile - package body to read. Name includes extension: FileName.vhd or FileName.vhdl
# PkgHeaderFile - package header to create
#
# For deferred constants of the form:
# constant ABC : type := SomeValue ;
# The package header (declation part) contains a declaration for the constant ABC:
# constant ABC : type ;
# The "package body" in PkgBodyFile is replaced with "package" in the PkgHeaderFile
#
set PkgHeaderFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${PkgHeaderFile}]
set NewPkgHeaderFilePath [GetNewName $PkgHeaderFilePath]
set PkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${PkgBodyFile}]
# Write to this file from a stream (sed): match these patterns Read this source file replace pattern with this
PrintTo ${NewPkgHeaderFilePath} [regsub -all {:=\s*[^;]+;} [regsub -all {package body} [ReadFrom ${PkgBodyFilePath}] "package"] ";"]
CopyFileIfDiffOtherwiseDelete $NewPkgHeaderFilePath $PkgHeaderFilePath
}
# -------------------------------------------------
# MakePkgBodyTemplate
#
proc MakePkgBodyTemplate {PkgBodyFile TemplatePkgBodyFile} {
#
# For a package body of deferred constants, create a package body template file
#
# PkgBodyFile - package body to read. Name includes extension: FileName.vhd or FileName.vhdl
# TemplatePkgBodyFile - package template file to create
#
# For deferred constants of the form:
# constant ABC : type := SomeValue ;
# The value "SomeValue" is replaced with ${ABC} in the template file, resulting in:
# constant ABC : type := ${ABC} ;
#
set PkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${PkgBodyFile}]
set TemplatePkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${TemplatePkgBodyFile}]
set NewTemplatePkgBodyFilePath [GetNewName $TemplatePkgBodyFilePath]
# Write to this file from a stream (sed): pattern to match Read this source file replace pattern with this
# PrintTo ${NewTemplatePkgBodyFilePath} [regsub -all -nocase {(constant\s+(\w+)\s*:\s*[^:=]+):=\s*[^;]+;} [ReadFrom ${PkgBodyFilePath}] {\1:= ${\2} ;}]
PrintTo ${NewTemplatePkgBodyFilePath} [regsub -all -linestop -nocase {(constant\s+(\w+)\s*:.*?):=\s*[^;]+;} [ReadFrom ${PkgBodyFilePath}] {\1:= ${\2} ;}]
CopyFileIfDiffOtherwiseDelete $NewTemplatePkgBodyFilePath $TemplatePkgBodyFilePath
}
# -------------------------------------------------
# MakePkgSettings
#
proc MakePkgSettings {PkgBodyFile SettingsFile} {
#
# For a package body of deferred constants, create a settings file
#
# PkgBodyFile - package body to read. Name includes extension: FileName.vhd or FileName.vhdl
# SettingsFile - Output. Name includes extension
#
# For deferred constants of the form:
# constant ABC : type := SomeValue ;
# Create a file with just the following:
# ABC: SomeValue
# Any line that does not contain the word constant is not in the YamlFile
#
set SettingsFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${SettingsFile}]
set NewSettingsFilePath [GetNewName $SettingsFilePath]
set PkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${PkgBodyFile}]
set OutputFile [open ${NewSettingsFilePath} w]
foreach item [ReadListFromFile ${PkgBodyFilePath}] {
# Only for lines that contain the word constant
if {![regexp {^\s*--} $item] && [regexp -nocase {constant} $item] } {
# Match this pattern in item create this in result
regsub -all -nocase -- {^\s*constant\s+(\w+)\s*:\s*[\w\.\(\)]+\s*:=\s*(.*?);.*$} $item {\1: \2} result
puts $OutputFile $result
}
}
close $OutputFile
CopyFileIfDiffOtherwiseDelete $NewSettingsFilePath $SettingsFilePath
}
# # -------------------------------------------------
# # ReadYamlSettings - local - Failed attempt at reading settings
# #
# proc ReadYamlSettings {YamlFile} {
# # reading as YAML fails since YAML removes "" from string values - these are needed
# # left here as a reminder to use ReadPkgSettings instead
# set SettingsDict [::yaml::yaml2dict -file [file join ${::osvvm::CurrentWorkingDirectory} ${YamlFile}]]
# dict for {VariableName VariableValue} $SettingsDict {
# uplevel 1 [list set $VariableName $VariableValue]
# }
# }
# -------------------------------------------------
# ReadPkgSettings - local
#
proc ReadPkgSettings {SettingsFile} {
#
# Get settings file from the SettingsFile and set the variable in the calling procedure
#
# SettingsFile - Settings to read
#
# For settings of the form:
# ABC: SomeValue
# Set the variable ABC with SomeValue in the *calling* procedure
# Note the file looks to be YAML, however, a YAML reader will
# remove the "" from the values and they need to be preserved
# So a simple reader and pattern match is used to extract the values instead
#
foreach line [ReadListFromFile [file join ${::osvvm::CurrentWorkingDirectory} ${SettingsFile}]] {
if {[regexp {^\s*([^:]+)\s*:\s*(.*)\s*$} $line -> VariableName VariableValue]} {
uplevel 1 [list set $VariableName $VariableValue]
}
}
}
# -------------------------------------------------
# MakePkgBody
#
proc MakePkgBody {OsvvmSettingsFile UserSettingsFile TemplatePkgBodyFile PkgBodyFile} {
#
# Read OSVVM and User settings and substitute these into template file to create a new PkgBodyFile
#
# OsvvmSettingsFile - OSVVM settings file that sets defaults for all of the variables in the template file
# UserSettingsFile - User settings file that overrides the default values set by OsvvmSettingsFile
# TemplatePkgBodyFile - Template package body file - created by MakePkgBodyTemplate
# PkgBodyFile - Package body file to create
#
# The OSVVM and User settings files shall have the format:
# TclVariableName: TclVariableValue
#
# For a PkgBodyFile named PkgBody.vhd, the template file shall be named PkgBody_template.vhd.
# The template file shall contain constant declarations whose value is defined by a Tcl variable
# and shall have the format:
# constant ABC : type := ${ABC} ;
#
# Read OSVVM and then User settings (to ensure user settings override OSVVM settings)
ReadPkgSettings ${OsvvmSettingsFile} ; # For OSVVM packages, in a subdirectory of OsvvmLibraries
ReadPkgSettings ${UserSettingsFile} ; # In a settings directory dedicated to a single project
# Derive template file name
set TemplatePkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${TemplatePkgBodyFile}] ; # For OSVVM packages, in a subdirectory of OsvvmLibraries
set PkgBodyFilePath [file join ${::osvvm::CurrentWorkingDirectory} ${PkgBodyFile}] ; # In the settings directory dedicated to a single project
set NewPkgBodyFilePath [GetNewName $PkgBodyFilePath] ; # In the settings directory dedicated to a single project
# Write to NewPkgBodyFilePath and substitute Tcl variables found in TemplatePkgBodyFilePath with their value
PrintTo ${NewPkgBodyFilePath} [subst [ReadFrom ${TemplatePkgBodyFilePath}]]
CopyFileIfDiffOtherwiseDelete $NewPkgBodyFilePath $PkgBodyFilePath
}
# -------------------------------------------------
# MakeSettingsPkg
#
proc MakeSettingsPkg {SettingsPkgBaseName} {
#
# For a package body of deferred constants, create the header, template, and settings (vset)
#
# SettingsPkgBaseName - base name of the package (which is named $SettingsPkgBaseName_default.vhd)
#
# **MakeSettingPkg calls:**
#
# * [MakePkgHeader] - Create the header package ${SettingsPkgBaseName}.vhd
# * [MakePkgBodyTemplate] - Create the template package ${SettingsPkgBaseName}_template.vhd
# * [MakePkgSettings] - Create the package settings in ${SettingsPkgBaseName}_default.vset
#
MakePkgHeader ${SettingsPkgBaseName}_default.vhd ${SettingsPkgBaseName}.vhd
MakePkgBodyTemplate ${SettingsPkgBaseName}_default.vhd ${SettingsPkgBaseName}_template.vhd
MakePkgSettings ${SettingsPkgBaseName}_default.vhd ${SettingsPkgBaseName}_default.vset
}
# -------------------------------------------------
# FindSettingsPkgBody
#
proc FindSettingsPkgBody {SettingsPkgBaseName} {
#
# Choose the package body from to use for $SettingsPkgBaseName either the settings directory or the local default, ${SettingsPkgBaseName}_default.vhd.
# If a settings file named ${SettingsPkgBaseName}_local.vset exists in the settings directory, Create ${SettingsPkgBaseName}_generated.vhd and return that name.
# Else if the file ${SettingsPkgBaseName}_local.vhd exists in the settings directory, then return that name.
# Otherwise return the local file name: ${SettingsPkgBaseName}_default.vhd
#
# **MakeSettingPkg calls:**
#
# * [FindOsvvmSettingsDirectory] - Locates the settings directory
# * [MakePkgBody] - Creates ${SettingsPkgBaseName}_generated.vhd using ${SettingsPkgBaseName}_local.vset from the settings directory
#
set SettingsDirectory [FindOsvvmSettingsDirectory]
if {[FileExists ${SettingsDirectory}/${SettingsPkgBaseName}_local.vset]} {
MakePkgBody ${SettingsPkgBaseName}_default.vset \
${SettingsDirectory}/${SettingsPkgBaseName}_local.vset \
${SettingsPkgBaseName}_template.vhd \
${SettingsDirectory}/${SettingsPkgBaseName}_generated.vhd
return "${SettingsDirectory}/${SettingsPkgBaseName}_generated.vhd"
} elseif {[FileExists $SettingsDirectory/${SettingsPkgBaseName}_local.vhd]} {
return "${SettingsDirectory}/${SettingsPkgBaseName}_local.vhd"
} else {
return "${SettingsPkgBaseName}_default.vhd"
}
}
# Don't export the following due to conflicts with Tcl built-ins
# map
namespace export CreateOsvvmScriptSettingsPkg FindOsvvmSettingsDirectory CreateAndAnalyzeTestSettingsPkg
namespace export CreateTestCaseCommonPkg
namespace export MakePkgHeader MakePkgBodyTemplate MakePkgSettings MakePkgBody
namespace export MakeSettingsPkg FindSettingsPkgBody
# end namespace ::osvvm
}